diff --git a/README.md b/README.md index 07217b8..52346d9 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,10 @@ Reusable agent plugins and skills following AGENTS/skills conventions. ## Plugins -| Plugin | Description | -| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [vault](./vault/) | Zettelkasten-style vault workflows for Obsidian notes | -| [development](./development/) | Agent context, PR fixups, CLI design, codebase-grounded landing copy, architecture mapping and whiteboard defense, OSS readiness and marketing, session log audits, bug verification, decision records, and self-hosted runners | +| Plugin | Description | +| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [vault](./vault/) | Zettelkasten-style vault workflows for Obsidian notes | +| [development](./development/) | Agent context, PR fixups, CLI design, codebase-grounded landing copy, architecture mapping and whiteboard defense, OSS readiness and marketing, session log audits, feature maps, bug verification, decision records, and self-hosted runners | ## Layout diff --git a/development/.codex-plugin/plugin.json b/development/.codex-plugin/plugin.json index 1ff7c0c..b40cdb7 100644 --- a/development/.codex-plugin/plugin.json +++ b/development/.codex-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "development", - "version": "0.0.9", - "description": "Developer workflow skills for agent context, PR fixups, CLI design, codebase-grounded landing copy, architecture mapping and whiteboard defense, OSS readiness, OSS marketing, session log audits, bug verification, decision records, and GitHub Actions self-hosted runners.", + "version": "0.0.10", + "description": "Developer workflow skills for agent context, PR fixups, CLI design, codebase-grounded landing copy, architecture mapping and whiteboard defense, OSS readiness, OSS marketing, session log audits, agent feature maps, bug verification, decision records, and GitHub Actions self-hosted runners.", "author": { "name": "Mark Phelps" }, @@ -45,13 +45,19 @@ "verify-bug", "bug-verification", "false-positives", - "triage" + "triage", + "feature-map", + "verification", + "qa", + "e2e", + "playwright", + "accessibility" ], "skills": "./skills/", "interface": { "displayName": "Development", - "shortDescription": "Agent context, PR fixup, CLI design, landing copy, architecture mapping and whiteboard defense, OSS readiness, marketing, session log audit, bug verification, decision records, and runner workflows", - "longDescription": "Development workflow skills for auditing agent context files, fixing existing GitHub PRs, designing humane command-line interfaces, writing product landing-page copy backed by shipped code, mapping codebase architecture and design rationale, preparing GitHub repos for open source release, sharpening OSS README positioning, mining local agent session logs for papercuts in your own tools, verifying whether claimed bugs are real, writing and maintaining decision and plan records (ADRs), and running GitHub Actions self-hosted runners on a Linux host.", + "shortDescription": "Agent context, PR fixup, CLI design, landing copy, architecture mapping and whiteboard defense, OSS readiness, marketing, session log audit, feature maps, bug verification, decision records, and runner workflows", + "longDescription": "Development workflow skills for auditing agent context files, fixing existing GitHub PRs, designing humane command-line interfaces, writing product landing-page copy backed by shipped code, mapping codebase architecture and design rationale, preparing GitHub repos for open source release, sharpening OSS README positioning, mining local agent session logs for papercuts in your own tools, building feature maps that let agents drive and verify an app, verifying whether claimed bugs are real, writing and maintaining decision and plan records (ADRs), and running GitHub Actions self-hosted runners on a Linux host.", "developerName": "Mark Phelps", "category": "Development", "capabilities": ["Read", "Write"], @@ -64,6 +70,7 @@ "Map this codebase into a layered architecture overview.", "Quiz me whiteboard-defense style on this system's flows, trade-offs, and failure modes.", "Turn this codebase map into doc and comment fixes on a branch.", + "Build a feature map so agents can drive and verify this app.", "Write landing-page copy for this product using only capabilities proven by its codebase.", "Fact-check this product pitch against the code that actually ships and provide an evidence table.", "Audit this repo for open source readiness and first-contributor friction.", diff --git a/development/AGENTS.md b/development/AGENTS.md index 9a70591..1aa6211 100644 --- a/development/AGENTS.md +++ b/development/AGENTS.md @@ -22,6 +22,8 @@ agent context. capabilities that are proven by shipped code - `context-file-tuneup`: audit and rewrite `CLAUDE.md` / `AGENTS.md` files so they stay short, specific, and grounded in the repo +- `feature-map`: build a repo-local verification skill listing each + user-facing feature, how to reach and drive it, and what to observe - `decision-records`: write or update decision and implementation-plan records (ADRs) in a repo's records directory, keep the registry table in sync, and preserve history through amendments and supersession @@ -57,6 +59,9 @@ agent context. evidence, keep defense records local under `.map/`, and never modify the working tree. `/whiteboard docs` writes only to a worktree branch, keeps source edits to a comments-only commit, and pushes only on confirmation. +- For feature maps, record only drive steps observed to work, drive local or + development environments only, never write secret values, and write only + inside the generated skill directory. - For bug verification, never touch the working tree (repros run only in a `git worktree` under `.verify/`), never fix code or open issues, and post verdicts to GitHub only after the user confirms each post. diff --git a/development/README.md b/development/README.md index 5bc60f2..f2f4255 100644 --- a/development/README.md +++ b/development/README.md @@ -3,24 +3,25 @@ Developer workflow skills for repo-facing agent context, GitHub PR follow-up, command-line interface design, codebase-grounded landing copy, architecture mapping and whiteboard defense, open source release preparation, audits of your -own agent session logs, bug-claim verification, decision records, and GitHub -Actions self-hosted runners. +own agent session logs, agent feature maps, bug-claim verification, decision +records, and GitHub Actions self-hosted runners. ## Skill Set -| Skill | What It Does | When to Invoke | -| --------------------------- | -------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `cli-design` | Designs and reviews command-line interfaces using clig.dev guidance. | When creating CLI commands, flags, help text, output contracts, error messages, or destructive workflows. | -| `codebase-landing-copy` | Writes product landing-page copy grounded in shipped code and an evidence ledger. | When writing or fact-checking landing pages, homepages, product pitches, hero copy, or store listings for a repo-backed product. | -| `context-file-tuneup` | Audits, rewrites, and tightens `CLAUDE.md` / `AGENTS.md` context files. | When reviewing, shrinking, restructuring, or improving agent context. | -| `decision-records` | Writes and maintains decision and plan records (ADRs) and their registry table, preserving history. | When recording an architecture, product, design, or dependency decision, amending or superseding a record, or starting a records directory. | -| `github-pr-fixup` | Addresses unresolved GitHub PR review comments and failing CI on the existing source branch. | When a user gives you an existing PR URL and wants review feedback or CI failures fixed without a new PR. | -| `github-self-hosted-runner` | Installs, registers, verifies, or removes namespaced GitHub Actions self-hosted runners on a Linux host. | When a user gives a repository or organization URL and wants a persistent runner managed by systemd. | -| `whiteboard` | Maps architecture and design rationale, then runs whiteboard-defense quizzes. | When the user explicitly invokes `/whiteboard` to map a codebase, explore a region, refresh a map, defend their understanding, or write fixes back to the repo's docs. | -| `verify-bug` | Rules on whether claimed bugs are real via an isolated Prover/Skeptic/Referee hearing. | When the user asks whether a bug is real, wants findings or review comments verified, or points at suspected bugs from a map. | -| `oss-marketing` | Sharpens README and public-doc positioning for first-time visitors. | When a repo needs launch copy, clearer positioning, or a README that explains what the project is. | -| `oss-repo-readiness` | Audits and prepares a repo for open source release, focused on developer experience. | When making a repo public, writing CONTRIBUTING or issue templates, or running a pre-launch checklist. | -| `session-log-audit` | Mines local agent session logs for papercuts and produces a ranked fix list. | When the user wants to know what is annoying about their own tool, or why they work around it. | +| Skill | What It Does | When to Invoke | +| --------------------------- | ---------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `cli-design` | Designs and reviews command-line interfaces using clig.dev guidance. | When creating CLI commands, flags, help text, output contracts, error messages, or destructive workflows. | +| `codebase-landing-copy` | Writes product landing-page copy grounded in shipped code and an evidence ledger. | When writing or fact-checking landing pages, homepages, product pitches, hero copy, or store listings for a repo-backed product. | +| `context-file-tuneup` | Audits, rewrites, and tightens `CLAUDE.md` / `AGENTS.md` context files. | When reviewing, shrinking, restructuring, or improving agent context. | +| `decision-records` | Writes and maintains decision and plan records (ADRs) and their registry table, preserving history. | When recording an architecture, product, design, or dependency decision, amending or superseding a record, or starting a records directory. | +| `feature-map` | Builds a repo-local verification skill mapping each feature's reach, drive steps, expected results, and gotchas. | When the user explicitly invokes `/feature-map` to build, refresh, or extend an app's feature map. | +| `github-pr-fixup` | Addresses unresolved GitHub PR review comments and failing CI on the existing source branch. | When a user gives you an existing PR URL and wants review feedback or CI failures fixed without a new PR. | +| `github-self-hosted-runner` | Installs, registers, verifies, or removes namespaced GitHub Actions self-hosted runners on a Linux host. | When a user gives a repository or organization URL and wants a persistent runner managed by systemd. | +| `whiteboard` | Maps architecture and design rationale, then runs whiteboard-defense quizzes. | When the user explicitly invokes `/whiteboard` to map a codebase, explore a region, refresh a map, defend their understanding, or write fixes back to the repo's docs. | +| `verify-bug` | Rules on whether claimed bugs are real via an isolated Prover/Skeptic/Referee hearing. | When the user asks whether a bug is real, wants findings or review comments verified, or points at suspected bugs from a map. | +| `oss-marketing` | Sharpens README and public-doc positioning for first-time visitors. | When a repo needs launch copy, clearer positioning, or a README that explains what the project is. | +| `oss-repo-readiness` | Audits and prepares a repo for open source release, focused on developer experience. | When making a repo public, writing CONTRIBUTING or issue templates, or running a pre-launch checklist. | +| `session-log-audit` | Mines local agent session logs for papercuts and produces a ranked fix list. | When the user wants to know what is annoying about their own tool, or why they work around it. | ## Notes @@ -43,6 +44,10 @@ Actions self-hosted runners. `docs/map/`. Its `docs` mode proposes doc and comment fixes on a separate branch; source files change only in a comments-only commit, and nothing is pushed without confirmation. +- Feature map records only drive steps it observed working, drives local or + development environments only, and writes into the generated `verify-` + skill directory. The generated skill keeps entries current as agents verify + their changes. - Whiteboard logs `suspected-bug` leads without investigating them; `verify-bug` rules on them. Neither skill depends on the other. - Bug verification never modifies the working tree. Repro tests run only in a diff --git a/development/skills/feature-map/SKILL.md b/development/skills/feature-map/SKILL.md new file mode 100644 index 0000000..8927759 --- /dev/null +++ b/development/skills/feature-map/SKILL.md @@ -0,0 +1,163 @@ +--- +name: feature-map +description: + Build and maintain a feature map for an app — short markdown files that tell + agents what each user-facing feature is, how a user reaches it, how to drive + it (selectors, commands, requests, accessibility identifiers), what result to + observe, and the gotchas — packaged as a repo-local verification skill that + agents load automatically when checking their changes. Drives each feature + live so recorded steps are verified, marks what it couldn't drive, and keeps + entries current through use. Supports web, CLI, HTTP API, and macOS apps. Only + run when the user invokes `/feature-map` by name. +disable-model-invocation: true +--- + +# Feature map + +Give agents a sitemap of the app they're changing, so they can verify their work +without rediscovering how to reach and drive each feature every time. The idea +comes from Lauren Tan's (@poteto) workflow: a set of short markdown files inside +a verification skill, one per feature, each saying what exists, how a user gets +there, how to drive it, and what trips people up. + +This skill is the **builder**. It writes a **generated skill** into the repo, +and that generated skill is what agents use day to day. Anyone working in the +repo gets the map without installing this skill. + +## Hard rules + +- **Only record steps you saw work.** A drive step is `verified` only if you + performed it and observed the expected result in this run. Everything else is + `unverified` with a reason. A wrong selector is worse than none, because + agents will trust it. +- **Drive local or development environments only.** Never drive production. If + the only reachable environment looks like production (real domain, real + customer data), stop and ask. +- **Ask before destructive or external actions:** deleting data, sending email + or messages, charging money, calling third-party APIs. Prefer read-only paths, + test accounts, and seeded data. +- **Never write secrets.** Credentials appear only as environment-variable names + (`$APP_TEST_PASSWORD`), never values, in any file. +- **Never modify source code.** The builder writes only inside the generated + skill directory. Gaps that need code changes (a missing test id, an unlabeled + control) go in the findings list. + +## Commands + +| Invocation | Action | +| ------------------------ | --------------------------------------------------------------------- | +| `/feature-map` | No map yet: build it. Map exists: report status and propose next step | +| `/feature-map refresh` | Re-drive stale and failed entries, add features with no entry yet | +| `/feature-map ` | Map or re-map one feature ("checkout", "the export command") | + +Bare `/feature-map` on an existing map reports, in chat: entries by status +(verified, unverified, stale), features found in code with no entry, and the +open findings, then recommends one next step. + +## Where the generated skill lives + +Detect the repo's harness and write to the matching project-skill path: + +- `.claude/` exists or CLAUDE.md is present → `.claude/skills/verify-/` +- `.agents/` exists or AGENTS.md is present with Codex-style config → + `.agents/skills/verify-/` +- Both or neither → ask once which to use. + +`` is a short slug of the app's name, so generated skills from different +repos stay distinct if someone installs them globally. Layout: + +```text +verify-/ +├── SKILL.md # index + verification loop (template in references/templates.md) +└── features/ + ├── .md # one per feature + └── ... +``` + +The generated files are ordinary markdown in the repo. The user decides whether +to commit them; say so in the report, and recommend committing, since the map +only helps other agents if it's shared. + +## Build + +### 1. Discover features (static) + +A feature is something a user or caller can do and observe: a page or flow, a +CLI command, an API operation, a menu or window in a native app. Find them from +the edges inward, the same way you would scout an architecture: + +- **Web:** router config, page and route files, navigation components, forms. +- **CLI:** the command tree (cobra, clap, click, commander, argparse), help + output (` --help`, recursively). +- **HTTP API:** route registrations, OpenAPI/proto definitions. +- **macOS:** menus (`CommandMenu`, `NSMenu`), windows and scenes, menu bar + extras (`MenuBarExtra`, `NSStatusItem`), settings panes, App Intents. + +Group fine-grained operations into features a user would name ("manage flags", +not "PUT /flags/:key"). Aim for entries a person could list from the product's +own navigation. If a `whiteboard` map exists in `docs/map/`, use its entry +points and regions as a head start and record the links (see below). + +Before driving anything, show the user the discovered feature list and the +environment you plan to drive (URL, binary, simulator), and confirm. + +### 2. Drive each feature (live) + +Read the driver reference for each platform involved before driving it: +`references/drivers/web.md`, `cli.md`, `api.md`, or `macos.md`. A repo can mix +platforms (a CLI plus a web UI); load only the drivers you use. + +For each feature: + +1. Reach it the way a user would, from the app's starting point. +2. Drive the main path and record each step in the driver's vocabulary. +3. Observe and record the result: what appears, what's returned, what exit code + and output a command gives. +4. Note gotchas you hit: loading delays, auth redirects, flags that hide the + feature, ordering dependencies, flaky elements. + +If you can't drive it (needs credentials you don't have, seeded data, a paid +account, an unsupported control), write the entry from what the code suggests +and mark it `unverified: `. Don't guess selectors; write "no stable +selector found" instead. + +Run features in parallel with subagents when the harness supports it and the +features don't share mutable state; otherwise drive them one at a time. + +### 3. Write the generated skill + +Use `references/templates.md` for the generated `SKILL.md` and for feature +entries. Keep each feature file short, roughly 20–60 lines. If one grows past +that, split it into sub-features. + +### 4. Report + +In chat: where the skill was written, entry counts by status, the findings list +(gaps that need code changes to be drivable), and a recommendation to commit the +generated skill. Don't restate the entries. + +## Findings + +Some features can't be driven reliably without a small code change: a web +control with no stable selector, a macOS view with no `accessibilityIdentifier`, +a CLI that only prints human-formatted output. Record these in the generated +`SKILL.md` under **Findings**, one line each with a receipt. Don't fix them. +They're the to-do list for making the app agent-verifiable. + +## Refresh + +1. For each entry, check staleness: + `git log --oneline ..HEAD -- `. Changed paths, + `unverified: failed ...` entries, and entries whose SHA is no longer an + ancestor of HEAD are due for a re-drive. +2. Re-scan for features with no entry. +3. Re-drive what's due, map what's new, and update the index. +4. Remove entries whose feature no longer exists, after confirming with the + user; note removals in the report. + +## Links to `whiteboard` + +If the repo has a `whiteboard` map, add `regions:` to each feature entry naming +the map regions that implement it. Don't edit the map from here; tell the user +the map's region files can list the features they power. Neither skill depends +on the other. diff --git a/development/skills/feature-map/agents/openai.yaml b/development/skills/feature-map/agents/openai.yaml new file mode 100644 index 0000000..5b1f887 --- /dev/null +++ b/development/skills/feature-map/agents/openai.yaml @@ -0,0 +1,2 @@ +policy: + allow_implicit_invocation: false diff --git a/development/skills/feature-map/references/drivers/api.md b/development/skills/feature-map/references/drivers/api.md new file mode 100644 index 0000000..887e259 --- /dev/null +++ b/development/skills/feature-map/references/drivers/api.md @@ -0,0 +1,34 @@ +# HTTP API driver + +Use `curl` (or the repo's own client) against a locally running server. + +## Launch + +Start the server with the repo's command, wait on a health endpoint, and record +both in the Environment section. Obtain auth the way a client would (login +endpoint, test token from a seed script) and reference it by env var. + +## Vocabulary + +Write each step as a request: + +```text +POST /api/v1/flags +Authorization: Bearer $APP_TEST_TOKEN +{"key": "demo", "enabled": false} +``` + +Keep bodies minimal: only the fields the feature needs. + +## Observe + +Record the status code and the response fields that matter, not the whole body. +For async operations, record how to observe completion (a follow-up GET, a +webhook, a status field). + +## Gotchas to check + +- Idempotency: can the drive be repeated, or does it need unique keys? +- Pagination, rate limits, and eventual consistency +- Required headers (content type, versioning, CSRF) +- Differences between the API and what the UI sends for the same feature diff --git a/development/skills/feature-map/references/drivers/cli.md b/development/skills/feature-map/references/drivers/cli.md new file mode 100644 index 0000000..09358a3 --- /dev/null +++ b/development/skills/feature-map/references/drivers/cli.md @@ -0,0 +1,36 @@ +# CLI driver + +Run the real binary, built the way the repo builds it (`go build`, +`cargo build`, `npm link`), not an imagined invocation. + +## Launch + +Record the build command and binary path. Use a temporary working directory and +config (`--config`, `HOME=$(mktemp -d)`, or the tool's own env var) so drives +don't touch the user's real config or data. + +## Vocabulary + +Write each step as the exact command: + +```text +$ plot session start --name demo +``` + +Include required env vars by name, stdin input, and working directory when they +matter. + +## Observe + +Record the exit code and the key lines of output, plus any files created or +changed. Prefer machine-readable output (`--json`, `--format json`) when the +tool has it, and note the fields that matter. For interactive prompts, record +the prompt text and the input given; if a TTY is required and can't be provided, +mark the entry unverified with that reason. + +## Gotchas to check + +- Output that differs between TTY and pipe (color, spinners, prompts) +- Global state (config files, caches, lockfiles) leaking between drives +- Commands that need network or credentials +- Destructive commands: drive them only against the temporary directory diff --git a/development/skills/feature-map/references/drivers/macos.md b/development/skills/feature-map/references/drivers/macos.md new file mode 100644 index 0000000..8fd80cf --- /dev/null +++ b/development/skills/feature-map/references/drivers/macos.md @@ -0,0 +1,49 @@ +# macOS driver + +Drive native apps through the accessibility tree. This works well for menus, +buttons, text fields, and windows; custom-drawn views and some menu bar extras +need accessibility identifiers added before they're drivable. + +## Launch + +Build with the repo's scheme +(`xcodebuild -scheme -configuration Debug build`) and launch the built +bundle (`open .app`). Record both. The first drive may need Accessibility +permission for the terminal or agent host; if the drive fails with a permissions +error, stop and ask the user to grant it in System Settings → Privacy & Security +→ Accessibility. + +## Choosing a driver + +- **The repo has UI tests (XCUITest):** prefer them. Drive through a focused + test with `xcodebuild test -only-testing:/` and record the test + name as the drive step. This is the most reliable path. +- **Otherwise:** use System Events via `osascript`, or an accessibility MCP if + the harness has one. + +## Vocabulary + +Write steps against accessibility identifiers first, then titles: + +```text +click menu item "New Feed…" of menu "File" of menu bar 1 +click button id "addFeedButton" of window "Cove" +set value of text field id "feedURL" to "https://example.com/feed.xml" +``` + +For menu bar extras, record how to open the extra (its status item's identifier +or title) as the first step. + +## Observe + +Record window titles, text of labels, enabled state of controls, and any +notification or status item change. Read values through the accessibility tree +rather than screenshots when possible. + +## Gotchas to check + +- Accessibility permission for the driving process +- SwiftUI views without `accessibilityIdentifier` (record a finding) +- Menu bar extras that only render while open +- Sandboxed file dialogs, which are hard to drive; seed files instead +- Login items, sleep/wake, or system state the feature depends on diff --git a/development/skills/feature-map/references/drivers/web.md b/development/skills/feature-map/references/drivers/web.md new file mode 100644 index 0000000..89d0b91 --- /dev/null +++ b/development/skills/feature-map/references/drivers/web.md @@ -0,0 +1,39 @@ +# Web driver + +Use a browser automation tool: Playwright (via the repo's own setup, the +Playwright MCP, or `npx playwright`), or a browser-control MCP if that's what +the harness has. + +## Launch + +Start the dev server with the repo's own command (`npm run dev`, `make run`). +Wait for a readiness signal (a log line or a 200 from the base URL) instead of a +fixed sleep. Record the command and signal in the generated `SKILL.md` +Environment section. + +## Vocabulary + +Write steps as user actions with locators, most stable first: + +1. Role and accessible name: `click button "Save flag"` +2. Label: `fill label "Email" with $APP_TEST_EMAIL` +3. Test id: `click [data-testid=flag-toggle]` +4. Visible text, only when unique and unlikely to change + +Avoid CSS class chains, nth-child, and XPath; they break on restyling. If no +stable locator exists, record a finding ("add `data-testid` or an accessible +name to the flag toggle"). + +## Observe + +Record what a user would see: headings, text, URL changes, toasts, and the +network response when it matters (`POST /api/flags → 201`). Take a screenshot +only when a result is visual and hard to put in words; don't store it in the +entry. + +## Gotchas to check + +- Auth redirects and session expiry +- Loading and optimistic UI (wait on the result, not a timer) +- Feature flags or roles that hide the feature +- Client-side routing that changes the URL without a page load diff --git a/development/skills/feature-map/references/templates.md b/development/skills/feature-map/references/templates.md new file mode 100644 index 0000000..af51965 --- /dev/null +++ b/development/skills/feature-map/references/templates.md @@ -0,0 +1,119 @@ +# Generated skill templates + +Templates for the files the builder writes into the repo. Fill every +placeholder; delete optional lines that don't apply. + +## Contents + +- Generated `SKILL.md` +- Feature entry +- Status markers + +## Generated `SKILL.md` + +The description must trigger when an agent in this repo is about to verify a +change, not on every question about the app. + +```markdown +--- +name: verify- +description: + Feature map for : how to reach, drive, and check each user-facing + feature. Use whenever you're verifying a change to — before calling a + task done, after editing UI, commands, or endpoints, or when asked to test + or QA a feature — so you drive the real behavior instead of guessing. +--- + +# Verify + + + +## Environment + +- Start: `` (ready when ) +- Base: +- Auth: +- Seed data: +- Drivers: + +## Verifying a change + +1. Find entries whose `paths` overlap your diff: + `git diff --name-only ...HEAD`, then match against each entry's `paths` + below. +2. Read those feature files and drive them, following the steps exactly. +3. Update each entry you drove, and only those: + - it worked → set `verified: `, fix any step you had to adjust, + and record what you actually observed; + - it failed because of your change → fix your change, not the entry; + - it failed because the entry is out of date → correct the steps from what + you observed, or set `unverified: failed at step on `. +4. If your change added a feature, add an entry for it using the same format. +5. If you needed a feature with no entry, say that the feature map could be + updated for it. + +Record what you observed, never what the code implies. + +## Features + +| Feature | File | Paths | Status | +| ------- | ---------------------------------------- | -------- | ---------------------- | +| | [features/.md](features/.md) | `` | verified `` | + +Verified: / + +## Findings + +- + (``) +``` + +## Feature entry + +`features/.md`: + +```markdown +--- +feature: +title: +platform: +paths: [, ...] +regions: [, ...] # optional +status: 'verified: ' # quoted: the value contains a colon +--- + +# + + + +## Reach + + + +## Drive + +1. +2. ... + +## Expect + +- + +## Gotchas + +- +``` + +## Status markers + +| Marker | Meaning | +| --------------------------------------- | ----------------------------------------------- | +| `verified: ` | Every step was driven and the result observed | +| `unverified: ` | Not driven: credentials, data, or no driver | +| `unverified: failed at step N on ` | Was verified; a later drive failed at that step | + +In frontmatter, always quote the status value, since every marker contains a +colon. + +An entry is **stale** when its `paths` changed since its verified SHA. Stale +entries keep their marker; the index and refresh treat them as due. diff --git a/development/skills/whiteboard/references/templates.md b/development/skills/whiteboard/references/templates.md index 312ef4d..5bac4fd 100644 --- a/development/skills/whiteboard/references/templates.md +++ b/development/skills/whiteboard/references/templates.md @@ -81,6 +81,7 @@ mapped_at: mapped_on: paths: [, ...] entry_points: [, ...] +features: [, ...] # optional: user-facing features this powers --- # diff --git a/skills/feature-map/SKILL.md b/skills/feature-map/SKILL.md new file mode 100644 index 0000000..8927759 --- /dev/null +++ b/skills/feature-map/SKILL.md @@ -0,0 +1,163 @@ +--- +name: feature-map +description: + Build and maintain a feature map for an app — short markdown files that tell + agents what each user-facing feature is, how a user reaches it, how to drive + it (selectors, commands, requests, accessibility identifiers), what result to + observe, and the gotchas — packaged as a repo-local verification skill that + agents load automatically when checking their changes. Drives each feature + live so recorded steps are verified, marks what it couldn't drive, and keeps + entries current through use. Supports web, CLI, HTTP API, and macOS apps. Only + run when the user invokes `/feature-map` by name. +disable-model-invocation: true +--- + +# Feature map + +Give agents a sitemap of the app they're changing, so they can verify their work +without rediscovering how to reach and drive each feature every time. The idea +comes from Lauren Tan's (@poteto) workflow: a set of short markdown files inside +a verification skill, one per feature, each saying what exists, how a user gets +there, how to drive it, and what trips people up. + +This skill is the **builder**. It writes a **generated skill** into the repo, +and that generated skill is what agents use day to day. Anyone working in the +repo gets the map without installing this skill. + +## Hard rules + +- **Only record steps you saw work.** A drive step is `verified` only if you + performed it and observed the expected result in this run. Everything else is + `unverified` with a reason. A wrong selector is worse than none, because + agents will trust it. +- **Drive local or development environments only.** Never drive production. If + the only reachable environment looks like production (real domain, real + customer data), stop and ask. +- **Ask before destructive or external actions:** deleting data, sending email + or messages, charging money, calling third-party APIs. Prefer read-only paths, + test accounts, and seeded data. +- **Never write secrets.** Credentials appear only as environment-variable names + (`$APP_TEST_PASSWORD`), never values, in any file. +- **Never modify source code.** The builder writes only inside the generated + skill directory. Gaps that need code changes (a missing test id, an unlabeled + control) go in the findings list. + +## Commands + +| Invocation | Action | +| ------------------------ | --------------------------------------------------------------------- | +| `/feature-map` | No map yet: build it. Map exists: report status and propose next step | +| `/feature-map refresh` | Re-drive stale and failed entries, add features with no entry yet | +| `/feature-map ` | Map or re-map one feature ("checkout", "the export command") | + +Bare `/feature-map` on an existing map reports, in chat: entries by status +(verified, unverified, stale), features found in code with no entry, and the +open findings, then recommends one next step. + +## Where the generated skill lives + +Detect the repo's harness and write to the matching project-skill path: + +- `.claude/` exists or CLAUDE.md is present → `.claude/skills/verify-/` +- `.agents/` exists or AGENTS.md is present with Codex-style config → + `.agents/skills/verify-/` +- Both or neither → ask once which to use. + +`` is a short slug of the app's name, so generated skills from different +repos stay distinct if someone installs them globally. Layout: + +```text +verify-/ +├── SKILL.md # index + verification loop (template in references/templates.md) +└── features/ + ├── .md # one per feature + └── ... +``` + +The generated files are ordinary markdown in the repo. The user decides whether +to commit them; say so in the report, and recommend committing, since the map +only helps other agents if it's shared. + +## Build + +### 1. Discover features (static) + +A feature is something a user or caller can do and observe: a page or flow, a +CLI command, an API operation, a menu or window in a native app. Find them from +the edges inward, the same way you would scout an architecture: + +- **Web:** router config, page and route files, navigation components, forms. +- **CLI:** the command tree (cobra, clap, click, commander, argparse), help + output (` --help`, recursively). +- **HTTP API:** route registrations, OpenAPI/proto definitions. +- **macOS:** menus (`CommandMenu`, `NSMenu`), windows and scenes, menu bar + extras (`MenuBarExtra`, `NSStatusItem`), settings panes, App Intents. + +Group fine-grained operations into features a user would name ("manage flags", +not "PUT /flags/:key"). Aim for entries a person could list from the product's +own navigation. If a `whiteboard` map exists in `docs/map/`, use its entry +points and regions as a head start and record the links (see below). + +Before driving anything, show the user the discovered feature list and the +environment you plan to drive (URL, binary, simulator), and confirm. + +### 2. Drive each feature (live) + +Read the driver reference for each platform involved before driving it: +`references/drivers/web.md`, `cli.md`, `api.md`, or `macos.md`. A repo can mix +platforms (a CLI plus a web UI); load only the drivers you use. + +For each feature: + +1. Reach it the way a user would, from the app's starting point. +2. Drive the main path and record each step in the driver's vocabulary. +3. Observe and record the result: what appears, what's returned, what exit code + and output a command gives. +4. Note gotchas you hit: loading delays, auth redirects, flags that hide the + feature, ordering dependencies, flaky elements. + +If you can't drive it (needs credentials you don't have, seeded data, a paid +account, an unsupported control), write the entry from what the code suggests +and mark it `unverified: `. Don't guess selectors; write "no stable +selector found" instead. + +Run features in parallel with subagents when the harness supports it and the +features don't share mutable state; otherwise drive them one at a time. + +### 3. Write the generated skill + +Use `references/templates.md` for the generated `SKILL.md` and for feature +entries. Keep each feature file short, roughly 20–60 lines. If one grows past +that, split it into sub-features. + +### 4. Report + +In chat: where the skill was written, entry counts by status, the findings list +(gaps that need code changes to be drivable), and a recommendation to commit the +generated skill. Don't restate the entries. + +## Findings + +Some features can't be driven reliably without a small code change: a web +control with no stable selector, a macOS view with no `accessibilityIdentifier`, +a CLI that only prints human-formatted output. Record these in the generated +`SKILL.md` under **Findings**, one line each with a receipt. Don't fix them. +They're the to-do list for making the app agent-verifiable. + +## Refresh + +1. For each entry, check staleness: + `git log --oneline ..HEAD -- `. Changed paths, + `unverified: failed ...` entries, and entries whose SHA is no longer an + ancestor of HEAD are due for a re-drive. +2. Re-scan for features with no entry. +3. Re-drive what's due, map what's new, and update the index. +4. Remove entries whose feature no longer exists, after confirming with the + user; note removals in the report. + +## Links to `whiteboard` + +If the repo has a `whiteboard` map, add `regions:` to each feature entry naming +the map regions that implement it. Don't edit the map from here; tell the user +the map's region files can list the features they power. Neither skill depends +on the other. diff --git a/skills/feature-map/agents/openai.yaml b/skills/feature-map/agents/openai.yaml new file mode 100644 index 0000000..5b1f887 --- /dev/null +++ b/skills/feature-map/agents/openai.yaml @@ -0,0 +1,2 @@ +policy: + allow_implicit_invocation: false diff --git a/skills/feature-map/references/drivers/api.md b/skills/feature-map/references/drivers/api.md new file mode 100644 index 0000000..887e259 --- /dev/null +++ b/skills/feature-map/references/drivers/api.md @@ -0,0 +1,34 @@ +# HTTP API driver + +Use `curl` (or the repo's own client) against a locally running server. + +## Launch + +Start the server with the repo's command, wait on a health endpoint, and record +both in the Environment section. Obtain auth the way a client would (login +endpoint, test token from a seed script) and reference it by env var. + +## Vocabulary + +Write each step as a request: + +```text +POST /api/v1/flags +Authorization: Bearer $APP_TEST_TOKEN +{"key": "demo", "enabled": false} +``` + +Keep bodies minimal: only the fields the feature needs. + +## Observe + +Record the status code and the response fields that matter, not the whole body. +For async operations, record how to observe completion (a follow-up GET, a +webhook, a status field). + +## Gotchas to check + +- Idempotency: can the drive be repeated, or does it need unique keys? +- Pagination, rate limits, and eventual consistency +- Required headers (content type, versioning, CSRF) +- Differences between the API and what the UI sends for the same feature diff --git a/skills/feature-map/references/drivers/cli.md b/skills/feature-map/references/drivers/cli.md new file mode 100644 index 0000000..09358a3 --- /dev/null +++ b/skills/feature-map/references/drivers/cli.md @@ -0,0 +1,36 @@ +# CLI driver + +Run the real binary, built the way the repo builds it (`go build`, +`cargo build`, `npm link`), not an imagined invocation. + +## Launch + +Record the build command and binary path. Use a temporary working directory and +config (`--config`, `HOME=$(mktemp -d)`, or the tool's own env var) so drives +don't touch the user's real config or data. + +## Vocabulary + +Write each step as the exact command: + +```text +$ plot session start --name demo +``` + +Include required env vars by name, stdin input, and working directory when they +matter. + +## Observe + +Record the exit code and the key lines of output, plus any files created or +changed. Prefer machine-readable output (`--json`, `--format json`) when the +tool has it, and note the fields that matter. For interactive prompts, record +the prompt text and the input given; if a TTY is required and can't be provided, +mark the entry unverified with that reason. + +## Gotchas to check + +- Output that differs between TTY and pipe (color, spinners, prompts) +- Global state (config files, caches, lockfiles) leaking between drives +- Commands that need network or credentials +- Destructive commands: drive them only against the temporary directory diff --git a/skills/feature-map/references/drivers/macos.md b/skills/feature-map/references/drivers/macos.md new file mode 100644 index 0000000..8fd80cf --- /dev/null +++ b/skills/feature-map/references/drivers/macos.md @@ -0,0 +1,49 @@ +# macOS driver + +Drive native apps through the accessibility tree. This works well for menus, +buttons, text fields, and windows; custom-drawn views and some menu bar extras +need accessibility identifiers added before they're drivable. + +## Launch + +Build with the repo's scheme +(`xcodebuild -scheme -configuration Debug build`) and launch the built +bundle (`open .app`). Record both. The first drive may need Accessibility +permission for the terminal or agent host; if the drive fails with a permissions +error, stop and ask the user to grant it in System Settings → Privacy & Security +→ Accessibility. + +## Choosing a driver + +- **The repo has UI tests (XCUITest):** prefer them. Drive through a focused + test with `xcodebuild test -only-testing:/` and record the test + name as the drive step. This is the most reliable path. +- **Otherwise:** use System Events via `osascript`, or an accessibility MCP if + the harness has one. + +## Vocabulary + +Write steps against accessibility identifiers first, then titles: + +```text +click menu item "New Feed…" of menu "File" of menu bar 1 +click button id "addFeedButton" of window "Cove" +set value of text field id "feedURL" to "https://example.com/feed.xml" +``` + +For menu bar extras, record how to open the extra (its status item's identifier +or title) as the first step. + +## Observe + +Record window titles, text of labels, enabled state of controls, and any +notification or status item change. Read values through the accessibility tree +rather than screenshots when possible. + +## Gotchas to check + +- Accessibility permission for the driving process +- SwiftUI views without `accessibilityIdentifier` (record a finding) +- Menu bar extras that only render while open +- Sandboxed file dialogs, which are hard to drive; seed files instead +- Login items, sleep/wake, or system state the feature depends on diff --git a/skills/feature-map/references/drivers/web.md b/skills/feature-map/references/drivers/web.md new file mode 100644 index 0000000..89d0b91 --- /dev/null +++ b/skills/feature-map/references/drivers/web.md @@ -0,0 +1,39 @@ +# Web driver + +Use a browser automation tool: Playwright (via the repo's own setup, the +Playwright MCP, or `npx playwright`), or a browser-control MCP if that's what +the harness has. + +## Launch + +Start the dev server with the repo's own command (`npm run dev`, `make run`). +Wait for a readiness signal (a log line or a 200 from the base URL) instead of a +fixed sleep. Record the command and signal in the generated `SKILL.md` +Environment section. + +## Vocabulary + +Write steps as user actions with locators, most stable first: + +1. Role and accessible name: `click button "Save flag"` +2. Label: `fill label "Email" with $APP_TEST_EMAIL` +3. Test id: `click [data-testid=flag-toggle]` +4. Visible text, only when unique and unlikely to change + +Avoid CSS class chains, nth-child, and XPath; they break on restyling. If no +stable locator exists, record a finding ("add `data-testid` or an accessible +name to the flag toggle"). + +## Observe + +Record what a user would see: headings, text, URL changes, toasts, and the +network response when it matters (`POST /api/flags → 201`). Take a screenshot +only when a result is visual and hard to put in words; don't store it in the +entry. + +## Gotchas to check + +- Auth redirects and session expiry +- Loading and optimistic UI (wait on the result, not a timer) +- Feature flags or roles that hide the feature +- Client-side routing that changes the URL without a page load diff --git a/skills/feature-map/references/templates.md b/skills/feature-map/references/templates.md new file mode 100644 index 0000000..af51965 --- /dev/null +++ b/skills/feature-map/references/templates.md @@ -0,0 +1,119 @@ +# Generated skill templates + +Templates for the files the builder writes into the repo. Fill every +placeholder; delete optional lines that don't apply. + +## Contents + +- Generated `SKILL.md` +- Feature entry +- Status markers + +## Generated `SKILL.md` + +The description must trigger when an agent in this repo is about to verify a +change, not on every question about the app. + +```markdown +--- +name: verify- +description: + Feature map for : how to reach, drive, and check each user-facing + feature. Use whenever you're verifying a change to — before calling a + task done, after editing UI, commands, or endpoints, or when asked to test + or QA a feature — so you drive the real behavior instead of guessing. +--- + +# Verify + + + +## Environment + +- Start: `` (ready when ) +- Base: +- Auth: +- Seed data: +- Drivers: + +## Verifying a change + +1. Find entries whose `paths` overlap your diff: + `git diff --name-only ...HEAD`, then match against each entry's `paths` + below. +2. Read those feature files and drive them, following the steps exactly. +3. Update each entry you drove, and only those: + - it worked → set `verified: `, fix any step you had to adjust, + and record what you actually observed; + - it failed because of your change → fix your change, not the entry; + - it failed because the entry is out of date → correct the steps from what + you observed, or set `unverified: failed at step on `. +4. If your change added a feature, add an entry for it using the same format. +5. If you needed a feature with no entry, say that the feature map could be + updated for it. + +Record what you observed, never what the code implies. + +## Features + +| Feature | File | Paths | Status | +| ------- | ---------------------------------------- | -------- | ---------------------- | +| | [features/.md](features/.md) | `` | verified `` | + +Verified: / + +## Findings + +- + (``) +``` + +## Feature entry + +`features/.md`: + +```markdown +--- +feature: +title: +platform: +paths: [, ...] +regions: [, ...] # optional +status: 'verified: ' # quoted: the value contains a colon +--- + +# + + + +## Reach + + + +## Drive + +1. +2. ... + +## Expect + +- + +## Gotchas + +- +``` + +## Status markers + +| Marker | Meaning | +| --------------------------------------- | ----------------------------------------------- | +| `verified: ` | Every step was driven and the result observed | +| `unverified: ` | Not driven: credentials, data, or no driver | +| `unverified: failed at step N on ` | Was verified; a later drive failed at that step | + +In frontmatter, always quote the status value, since every marker contains a +colon. + +An entry is **stale** when its `paths` changed since its verified SHA. Stale +entries keep their marker; the index and refresh treat them as due. diff --git a/skills/whiteboard/references/templates.md b/skills/whiteboard/references/templates.md index 312ef4d..5bac4fd 100644 --- a/skills/whiteboard/references/templates.md +++ b/skills/whiteboard/references/templates.md @@ -81,6 +81,7 @@ mapped_at: mapped_on: paths: [, ...] entry_points: [, ...] +features: [, ...] # optional: user-facing features this powers --- #