featureparity 0.0.28 → 0.0.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/fp/cli.rb +11 -2
- data/lib/fp/client.rb +31 -1
- data/lib/fp/commands/base.rb +14 -0
- data/lib/fp/commands/check.rb +38 -4
- data/lib/fp/commands/ci_report.rb +35 -5
- data/lib/fp/commands/comment.rb +1 -1
- data/lib/fp/commands/coverage.rb +149 -0
- data/lib/fp/commands/doctor.rb +228 -0
- data/lib/fp/commands/help.rb +13 -1
- data/lib/fp/commands/history.rb +4 -0
- data/lib/fp/commands/init.rb +172 -117
- data/lib/fp/commands/list.rb +58 -4
- data/lib/fp/commands/mark.rb +167 -0
- data/lib/fp/commands/projects.rb +1 -0
- data/lib/fp/commands/propose.rb +401 -52
- data/lib/fp/commands/propose_change.rb +7 -1
- data/lib/fp/commands/question.rb +137 -0
- data/lib/fp/commands/report.rb +23 -3
- data/lib/fp/commands/run.rb +147 -0
- data/lib/fp/commands/show.rb +27 -0
- data/lib/fp/commands.rb +5 -0
- data/lib/fp/junit.rb +60 -7
- data/lib/fp/repo_detector.rb +488 -0
- data/lib/fp/requirement_lint.rb +105 -0
- data/lib/fp/rspec_json.rb +54 -0
- data/lib/fp/version.rb +1 -1
- data/lib/fp.rb +1 -0
- data/skills/fp/SKILL.md +244 -105
- data/skills/fp/references/cli.md +231 -3
- metadata +10 -2
data/skills/fp/SKILL.md
CHANGED
|
@@ -17,6 +17,14 @@ command -v fp && fp --version
|
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
If missing: `gem install featureparity` (or `bundle exec fp` inside an app that already depends on the gem).
|
|
20
|
+
`fp doctor` checks the install, the config and the repo without an API key. If `fp` fails
|
|
21
|
+
inside a repo but works elsewhere, see Troubleshooting.
|
|
22
|
+
|
|
23
|
+
**Already read the repo's FeatureParity section?** `fp init` writes one into `AGENTS.md`
|
|
24
|
+
(or `CLAUDE.md`), and it carries the modeling rules (§1), the requirement-writing standard
|
|
25
|
+
(§5), onboarding and troubleshooting from this file word for word, between the same
|
|
26
|
+
`fp-shared` comments. This file is their source. Skip those blocks if you've read them
|
|
27
|
+
there; the rest of this skill is the command reference.
|
|
20
28
|
|
|
21
29
|
## Non-interactive rules
|
|
22
30
|
|
|
@@ -49,6 +57,8 @@ every project the user belongs to; never ask for a per-project key.
|
|
|
49
57
|
fp list --project stowzilla # All active requirements
|
|
50
58
|
fp list --project stowzilla --status draft # Proposed work; avoid duplicates
|
|
51
59
|
fp list --project stowzilla --gaps # Requirements with a required surface lacking evidence
|
|
60
|
+
fp list --project stowzilla --status draft --gaps # Drafts with a required surface lacking evidence
|
|
61
|
+
fp coverage --project stowzilla # Drafts × surfaces, then the drafts with no evidence
|
|
52
62
|
fp show <slug> --project stowzilla # Requirement details and evidence
|
|
53
63
|
fp history <slug> --project stowzilla # Origins and pending changes
|
|
54
64
|
fp changes --source-url <work-item-url> # Activity prompted by one card, issue, or thread
|
|
@@ -57,25 +67,32 @@ fp matrix --project stowzilla --csv # Export as CSV
|
|
|
57
67
|
fp check --project stowzilla # Enforce parity (exits 1 on violations)
|
|
58
68
|
```
|
|
59
69
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
-
|
|
77
|
-
|
|
78
|
-
|
|
70
|
+
<!-- fp-shared:begin modeling -->
|
|
71
|
+
**The requirement catalog is the human-readable product specification, not a box to
|
|
72
|
+
tick with one umbrella record.** It records the team's current shared understanding;
|
|
73
|
+
it is not a finished decree handed from product to engineering. Refine requirements
|
|
74
|
+
through ongoing conversation with customers, domain experts, and builders. The human
|
|
75
|
+
product owner decides value and priority; agents should surface gaps, inconsistencies,
|
|
76
|
+
alternatives, and useful splits rather than silently making product decisions.
|
|
77
|
+
|
|
78
|
+
Before coding, enumerate the independently meaningful promises in the request:
|
|
79
|
+
user-visible behaviours, policies, limits, plans, deadlines, state transitions,
|
|
80
|
+
permissions, failure modes, and affected surfaces. Then model them:
|
|
81
|
+
|
|
82
|
+
- Give each independently testable or independently failable product promise its own
|
|
83
|
+
focused requirement. If one acceptance sentence joins behaviours that could pass or
|
|
84
|
+
fail separately, split it.
|
|
85
|
+
- Use a parent for the broad capability and children for distinct behaviours, policies,
|
|
86
|
+
or surface-specific promises. Do not create requirements for implementation details
|
|
87
|
+
or refactors that make no product promise.
|
|
88
|
+
- Put concrete product decisions — prices, quotas, dates, roles, fallbacks — in the
|
|
89
|
+
requirement acceptance criteria. Never leave them only as assumptions in code or a PR.
|
|
90
|
+
- Check adjacent requirements and their history. New requirements do not excuse an old
|
|
91
|
+
requirement that the work makes inaccurate; propose a change to keep the whole catalog true.
|
|
92
|
+
- Before finishing, reconcile the implementation against the catalog: every shipped
|
|
93
|
+
behaviour maps to a current requirement, every changed promise is recorded, and every
|
|
94
|
+
focused requirement has appropriate marked evidence or an explicit gap. A broad marker
|
|
95
|
+
must never appear to prove several acceptance clauses that its test does not exercise.
|
|
79
96
|
|
|
80
97
|
**Prevent contradictions before they enter the catalog.** Before proposing a new or changed
|
|
81
98
|
promise, compare its intended acceptance criteria with related active and draft requirements
|
|
@@ -83,31 +100,35 @@ and read their history. Ask whether both promises can be true at the same time f
|
|
|
83
100
|
user, state, and conditions. If not, do not add another requirement.
|
|
84
101
|
|
|
85
102
|
A failing test bound to an existing requirement, or an implementation that only works by
|
|
86
|
-
changing one, is a contradiction signal — not permission to weaken the test or write a
|
|
87
|
-
requirement around it. Identify which promise matches product intent, then use
|
|
88
|
-
`fp propose-change` (or `--removal`) with the source and reason to put that decision before
|
|
89
|
-
human. If the intent is unclear, stop and ask rather than making the catalog say both things.
|
|
103
|
+
changing one, is a contradiction signal — not permission to weaken the test or write a
|
|
104
|
+
second requirement around it. Identify which promise matches product intent, then use
|
|
105
|
+
`fp propose-change` (or `--removal`) with the source and reason to put that decision before
|
|
106
|
+
a human. If the intent is unclear, stop and ask rather than making the catalog say both things.
|
|
90
107
|
|
|
91
108
|
**Treat existing tests as protected product evidence.** Before editing an existing test,
|
|
92
109
|
determine what expectation it already records and whether CI has passing evidence for it.
|
|
93
110
|
|
|
94
|
-
- If the test backs passing evidence, do not rewrite it to make the current implementation
|
|
95
|
-
new requirement fit. Explicitly flag the intended test edit in the work item and pull
|
|
96
|
-
If its expected behaviour would change, propose the requirement change and wait
|
|
97
|
-
human approval before editing the test; a newly green run must not hide that
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
+
- If the test backs passing evidence, do not rewrite it to make the current implementation
|
|
112
|
+
or a new requirement fit. Explicitly flag the intended test edit in the work item and pull
|
|
113
|
+
request. If its expected behaviour would change, propose the requirement change and wait
|
|
114
|
+
for explicit human approval before editing the test; a newly green run must not hide that
|
|
115
|
+
the proof itself changed.
|
|
116
|
+
- When FeatureParity reports a changed bound test, run `fp changed-tests` (or add `--json`)
|
|
117
|
+
and compare the accepted and candidate source revisions with the requirement. Record the
|
|
118
|
+
exact candidate through `fp changed-tests assess <id> --candidate-fingerprint <sha256>`
|
|
119
|
+
with a plain-language explanation and one classification: `still_proves`,
|
|
120
|
+
`no_longer_proves`, or `uncertain`. The first resolves only that fingerprint; the others
|
|
121
|
+
remain open for a human product decision. A later fingerprint needs a new assessment.
|
|
122
|
+
- A new requirement does not retroactively own or supersede a pre-existing failing test —
|
|
123
|
+
whether the requirement is draft or active. Do not change that test, or adopt it as the new
|
|
124
|
+
requirement's proof, merely to make the new work pass. Surface the conflict and wait for
|
|
125
|
+
explicit human approval to change the existing expectation.
|
|
126
|
+
|
|
127
|
+
A changed-test finding is an audit signal alongside the testcase's independent CI outcome.
|
|
128
|
+
It is not a failed test and is separate from `suspect`, which means requirement wording
|
|
129
|
+
changed and its evidence needs re-verification. Neither permits rewriting a test before
|
|
130
|
+
product intent is decided.
|
|
131
|
+
<!-- fp-shared:end modeling -->
|
|
111
132
|
|
|
112
133
|
### 2. Add the fp:<slug> marker to tests
|
|
113
134
|
|
|
@@ -151,16 +172,26 @@ first CI run, or local work where CI isn't wired up. When you do report over a C
|
|
|
151
172
|
cell anyway, `fp report` now tells you it was superseded (the status stays CI's, your
|
|
152
173
|
report lands as metadata only) so you can see the no-op instead of assuming it took.
|
|
153
174
|
|
|
154
|
-
### 4. Report evidence from
|
|
175
|
+
### 4. Report evidence from a test run (batch upload without CI)
|
|
176
|
+
|
|
177
|
+
When CI isn't available, run the suite locally and upload the report. `fp run` adds a
|
|
178
|
+
report formatter to rspec, pytest, vitest or playwright itself, so the project needs no
|
|
179
|
+
new dependency, then reports exactly as `fp report --junit` would:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
fp run --surface api --repo stowzilla/marketplace \
|
|
183
|
+
--work-item https://app.fizzy.do/123/cards/456 -- bundle exec rspec
|
|
184
|
+
```
|
|
155
185
|
|
|
156
|
-
|
|
186
|
+
Or make the report yourself. `--junit` takes JUnit XML or RSpec's built-in JSON, which
|
|
187
|
+
needs no extra gem (`fp init --detect` prints the command for each runner it finds):
|
|
157
188
|
|
|
158
189
|
```bash
|
|
159
|
-
# 1.
|
|
160
|
-
rspec --format
|
|
190
|
+
# 1. Write a report
|
|
191
|
+
bundle exec rspec --format progress --format json --out rspec.json
|
|
161
192
|
|
|
162
193
|
# 2. Upload — one call covers every marked test
|
|
163
|
-
fp report --junit
|
|
194
|
+
fp report --junit rspec.json \
|
|
164
195
|
--project stowzilla \
|
|
165
196
|
--surface api \
|
|
166
197
|
--repo stowzilla/marketplace \
|
|
@@ -173,79 +204,95 @@ fp report --junit junit.xml \
|
|
|
173
204
|
- `--surface` is the default; markers can override with `@suffix`
|
|
174
205
|
- `--base-dir DIR` sets where relative paths resolve from
|
|
175
206
|
|
|
207
|
+
#### Optional: attach screenshots and video, with permission
|
|
208
|
+
|
|
209
|
+
<!-- fp-shared:begin media -->
|
|
210
|
+
**Media is optional, and only with permission.** A test that drives a user interface can
|
|
211
|
+
carry the screenshots and videos it recorded as visual evidence, shown under that test's
|
|
212
|
+
receipt on the requirement page. Nothing requires it: a receipt counts the same with or
|
|
213
|
+
without media, and a capture never changes a cell's state. Uploading stores the files in
|
|
214
|
+
FeatureParity, so:
|
|
215
|
+
|
|
216
|
+
- **Ask first.** Upload only when the person you're working for has said yes, for this
|
|
217
|
+
project. Don't do it by default, and don't take "the run recorded something" as permission.
|
|
218
|
+
- **Never capture someone's own screen.** No screenshots or recordings of their desktop,
|
|
219
|
+
terminal, browser session or other windows. Only what an automated test drove (a
|
|
220
|
+
Playwright browser, a simulator or emulator the test launched) can be attached, and only
|
|
221
|
+
with that permission.
|
|
222
|
+
- **Look before you upload.** Don't attach a capture that shows real people's data, secrets
|
|
223
|
+
or anything outside the test.
|
|
224
|
+
|
|
225
|
+
When you have the go-ahead:
|
|
226
|
+
|
|
227
|
+
- **Playwright** lists its recorded files in the JUnit report as `[[ATTACHMENT|…]]`.
|
|
228
|
+
`fp report --junit results.xml --surface web --repo <org/repo> --attach-media` uploads
|
|
229
|
+
one set per bound test, titled with the test's name. It also works with `fp run ... -- npx playwright test`.
|
|
230
|
+
Without `--attach-media`, nothing is uploaded; fp only says how many captures it found.
|
|
231
|
+
- **One capture from a test** (for example an XCUITest or Espresso recording):
|
|
232
|
+
`fp attach <slug> <file> --surface <surface> --example-title "<test name>"`.
|
|
233
|
+
- png, jpg, gif, webp, mp4, webm or mov, up to 100 MB. `fp attachments <slug>` lists them;
|
|
234
|
+
`fp attach rm <slug> <id>` removes one.
|
|
235
|
+
<!-- fp-shared:end media -->
|
|
236
|
+
|
|
176
237
|
### 5. Write and propose decision-ready requirements
|
|
177
238
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
robust experience.”
|
|
212
|
-
- **Acceptance:** one independently verifiable rule of observable behaviour that lets someone
|
|
213
|
-
decide whether the promise is true. State the relevant trigger or situation, the result, and
|
|
214
|
-
material boundaries that qualify that same promise. Given/When/Then may clarify those parts, but it
|
|
215
|
-
is not a mandatory template. Split a second result that could fail independently into its
|
|
216
|
-
own requirement instead of comma-chaining it here.
|
|
217
|
-
- **Example:** supply one concise concrete case that would pass the general rule, and put it
|
|
218
|
-
after the rule in Acceptance as `Example: ...`. Use the domain's real terms and
|
|
219
|
-
representative data, but ask rather than invent consequential policy. Do not mistake a few
|
|
220
|
-
examples for the rule or let executable tests stand for every case; neither replaces the
|
|
221
|
-
general rule and continued conversation.
|
|
222
|
-
- **Numbers and policy:** include a number only when the source made it a real product decision
|
|
223
|
-
or an external constraint requires it. Do not invent implementation defaults and present
|
|
224
|
-
them as scope.
|
|
225
|
-
- **Implementation detail:** omit components, data models, algorithms, endpoints, polling
|
|
226
|
-
intervals, and UI controls unless that interface or constraint is itself user-visible policy.
|
|
239
|
+
<!-- fp-shared:begin writing -->
|
|
240
|
+
**Write a requirement as a product decision someone can approve, not as a design
|
|
241
|
+
task.** It should read like a capable teammate wrote it: direct, specific, and free
|
|
242
|
+
of boilerplate such as “ensure a seamless experience.”
|
|
243
|
+
|
|
244
|
+
- **Title:** one clear product promise in present tense, with a concrete subject and
|
|
245
|
+
active verb. Name the user-visible capability, not the work (`“Dispatchers see
|
|
246
|
+
current shipment status”`, not `“Implement status polling”`).
|
|
247
|
+
- **Why:** one natural sentence naming who needs this, the problem or risk, and the
|
|
248
|
+
outcome worth protecting. Do not repeat the title, narrate the request or bug
|
|
249
|
+
history, sell the feature, or explain the mechanism.
|
|
250
|
+
- **Acceptance:** one independently verifiable rule of observable behaviour that lets a
|
|
251
|
+
reviewer decide whether the promise is true. State the trigger or situation, the result, and material
|
|
252
|
+
boundaries that qualify that same promise. Given/When/Then may clarify those parts,
|
|
253
|
+
but it is not a mandatory template. Split a second result that could fail
|
|
254
|
+
independently into its own requirement instead of comma-chaining it here.
|
|
255
|
+
- **Example:** supply one concise concrete case that would pass the general rule, and
|
|
256
|
+
put it after the rule in Acceptance as `Example: ...`. Use the domain's real terms
|
|
257
|
+
and representative data, but ask rather than invent consequential policy. Do not mistake a few examples for the rule
|
|
258
|
+
or let marked tests stand for every case; neither replaces the general rule and
|
|
259
|
+
continued conversation.
|
|
260
|
+
- **Numbers and policy:** include a price, limit, timeout, date, role, or fallback only
|
|
261
|
+
when the source made it a real product decision or an external constraint requires it.
|
|
262
|
+
Never invent a plausible value to fill a gap. If the decision matters and the source is
|
|
263
|
+
silent, ask.
|
|
264
|
+
- **Implementation detail:** leave out components, data models, algorithms, endpoints,
|
|
265
|
+
and UI controls unless that interface or constraint is itself part of the promise.
|
|
266
|
+
|
|
267
|
+
Learn from the request, existing requirements and history, and available evidence about
|
|
268
|
+
what users actually do. Look for what they attempt, where they abandon a task, what they
|
|
269
|
+
use, and what experiments reveal. Treat the first proposed solution as input, not
|
|
270
|
+
unquestionable scope. Preserve important uncertainty as a question rather than
|
|
271
|
+
laundering a guess into acceptance criteria.
|
|
227
272
|
|
|
228
273
|
State the promise itself rather than commentary about it. Avoid openings such as “This
|
|
229
274
|
feature…”, “This requirement…”, “The goal is…”, “Users should be able to…”, and “The
|
|
230
275
|
system should…”. Use the real actor or product as the subject and an active verb.
|
|
231
276
|
|
|
232
|
-
A good requirement is concise, not merely short. Keep every sentence that changes a decision;
|
|
233
|
-
remove everything that only sounds thorough.
|
|
234
|
-
|
|
235
277
|
- ✅ **Title:** `Dispatchers see current shipment status`
|
|
236
278
|
**Why:** `Dispatchers need to spot delayed shipments before they miss a delivery window.`
|
|
237
279
|
**Acceptance:** `When a shipment's status changes, the dashboard shows the new status; if status is unavailable, it says so instead of presenting stale data as current.`
|
|
238
280
|
- ❌ **Title:** `Implement Redis-backed 30-second status polling`
|
|
239
281
|
**Why:** `This important feature ensures a seamless, robust experience.`
|
|
240
282
|
**Acceptance:** `Use a background worker and refresh every 30 seconds.`
|
|
241
|
-
This invents policy, prescribes a design, and never states the outcome.
|
|
283
|
+
This invents policy, prescribes a design, and never states the product outcome.
|
|
242
284
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
285
|
+
A good requirement is concise, not merely short: keep every sentence that changes a
|
|
286
|
+
decision and remove everything that only sounds thorough.
|
|
287
|
+
|
|
288
|
+
Before proposing, answer three questions against the actual fields: Who is this promise
|
|
289
|
+
for? How would the concrete example prove it done? Why does the outcome matter? If any
|
|
290
|
+
answer is missing or vague, revise the draft or ask the user. Then read it as a manager deciding scope:
|
|
291
|
+
is the value clear, can the result be observed, are product decisions
|
|
292
|
+
distinguished from guesses, could any clause fail on its own (then split it), and does
|
|
293
|
+
every sentence earn its place? If the draft fails
|
|
294
|
+
this review, revise it or ask before writing the record.
|
|
295
|
+
<!-- fp-shared:end writing -->
|
|
249
296
|
|
|
250
297
|
Then create the proposal as a draft:
|
|
251
298
|
|
|
@@ -262,6 +309,37 @@ fp propose --project stowzilla \
|
|
|
262
309
|
|
|
263
310
|
**Agents always create requirements as draft.** A human must activate them in the web app.
|
|
264
311
|
|
|
312
|
+
When no card or issue prompted it — you wrote the requirement by reading the code, as when
|
|
313
|
+
onboarding a repo — pass `--source-type repo_scan` and one `--source-ref path:line` for each
|
|
314
|
+
place you read it from.
|
|
315
|
+
|
|
316
|
+
Proposing several at once? Put them in a YAML file and run `fp propose --file reqs.yml
|
|
317
|
+
--dry-run` first. It lints every entry's wording and checks slugs and parents against the
|
|
318
|
+
catalog without writing anything. Then run it without `--dry-run`: the batch is created only if
|
|
319
|
+
every entry is valid. Bind tests with `fp mark <slug> <file>:<line>` rather than typing
|
|
320
|
+
markers by hand.
|
|
321
|
+
|
|
322
|
+
**Confirm draft coverage with `fp coverage`.** The gate measures only active requirements,
|
|
323
|
+
so while everything you proposed is still a draft `fp check` says "Nothing to enforce yet"
|
|
324
|
+
and `fp list --gaps` finds nothing. `fp coverage` shows each draft × surface resolved from
|
|
325
|
+
the evidence you reported, and ends with the drafts that have no evidence on a required
|
|
326
|
+
surface — hand that list to the human as the requirements with no test yet. Drafts are
|
|
327
|
+
reported, never gated. `fp check --include-drafts` appends the same table to the verdict.
|
|
328
|
+
|
|
329
|
+
**Attach your questions to the drafts they concern.** When a draft leaves a decision only a
|
|
330
|
+
human can make (a limit the source never set, a role it didn't name), don't leave the question
|
|
331
|
+
in chat, where it's cut off from the draft. Ask it on the draft:
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
fp question upload_limits "Is the 5 MB cap per file or per upload?"
|
|
335
|
+
fp questions upload_limits # open and answered questions, with the answers
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
The human reviewing that draft in Quick Review sees the question beside it and answers or
|
|
339
|
+
dismisses it there; `fp show` lists the open ones. Agents can ask but never answer. If the
|
|
340
|
+
user asks you for "a list of questions for the human", ask each one on its draft and give
|
|
341
|
+
them the list too. Draft and active requirements take questions.
|
|
342
|
+
|
|
265
343
|
### 6. Propose a change to an existing requirement
|
|
266
344
|
|
|
267
345
|
When a requirement no longer says the right thing, don't silently edit it — propose the
|
|
@@ -464,6 +542,40 @@ the command relays the upgrade message if that's used up. `fp projects delete` e
|
|
|
464
542
|
asks a human to type the slug back (or `--yes` in scripts) and is owner-only — don't reach
|
|
465
543
|
for it to tidy up; a project's requirements, evidence, and history go with it.
|
|
466
544
|
|
|
545
|
+
### Onboarding a repo (first run)
|
|
546
|
+
|
|
547
|
+
<!-- fp-shared:begin onboarding -->
|
|
548
|
+
The per-task loop assumes a catalog already describes the product. On a repo's first run
|
|
549
|
+
there isn't one yet, so the job is to write it down, as drafts a human activates, rather
|
|
550
|
+
than to check work against it.
|
|
551
|
+
|
|
552
|
+
1. `fp doctor` confirms fp runs under the repo's Ruby and shows which API it writes to,
|
|
553
|
+
then lists the repo's test runners, database and devcontainer.
|
|
554
|
+
2. `fp init --detect` suggests a project slug, surfaces, and the command that makes each
|
|
555
|
+
test runner write a report. If the project doesn't exist yet, create it with
|
|
556
|
+
`fp projects create <slug> --name "..." --surfaces <keys>`, then run
|
|
557
|
+
`fp init --project <slug>`.
|
|
558
|
+
3. Pick surfaces by this rubric, not by the folder layout. A surface is somewhere a user
|
|
559
|
+
interacts with the product: a web app, an iOS or Android app, a desktop app, a CLI, or
|
|
560
|
+
an API that customers call directly. An internal API with no separate client is not
|
|
561
|
+
one; its tests are evidence for the surface the user touches.
|
|
562
|
+
4. Propose what the code already promises as drafts, written to the requirement-writing
|
|
563
|
+
standard. Review a batch with `fp propose --file <file> --dry-run`, then send it without
|
|
564
|
+
`--dry-run`. Pass `--source-type repo_scan` and name the files you read in
|
|
565
|
+
`--source-context`.
|
|
566
|
+
5. Bind the tests that already prove each draft with `fp mark <slug> <file>:<line>`, or
|
|
567
|
+
write the `fp:<slug>` comment yourself.
|
|
568
|
+
6. Report with `fp run --surface <key> --repo <org/repo> -- <test command>`. It adds the
|
|
569
|
+
report formatter for rspec, pytest, vitest and playwright, so the project needs no new
|
|
570
|
+
dependency. For any other runner, use `fp report --junit <file>`.
|
|
571
|
+
7. `fp coverage` lists the drafts that still have no evidence. When the code doesn't settle
|
|
572
|
+
a product decision (a limit, a role, a fallback), attach the question to the draft with
|
|
573
|
+
`fp question <slug> "<text>"` instead of guessing an answer.
|
|
574
|
+
8. Commit `.featureparity.yml`, the workflow and the agent docs. Committing the workflow
|
|
575
|
+
before anyone has added the `FP_API_KEY` secret is fine: the gate skips with an
|
|
576
|
+
explanation and the build stays green until the secret exists.
|
|
577
|
+
<!-- fp-shared:end onboarding -->
|
|
578
|
+
|
|
467
579
|
### Triage requirement quality (`fp analyze`)
|
|
468
580
|
|
|
469
581
|
`fp analyze` checks how well requirements are written and whether they belong in the
|
|
@@ -495,20 +607,47 @@ not as the fix — you still write the proposal.
|
|
|
495
607
|
| Not a product promise / not observable | A human decides whether it belongs; don't guess |
|
|
496
608
|
| Missing why, vague acceptance, implementation detail, boilerplate | `fp propose-change <slug> --why "..." --acceptance "..."` |
|
|
497
609
|
|
|
610
|
+
## Troubleshooting
|
|
611
|
+
|
|
612
|
+
<!-- fp-shared:begin troubleshooting -->
|
|
613
|
+
- **`mise ERROR No version is set for shim: fp`** inside a repo, while `fp` works from
|
|
614
|
+
another directory (rbenv and asdf say `fp` isn't installed): the repo pins a Ruby in
|
|
615
|
+
`.ruby-version`, `.tool-versions` or `mise.toml` that the featureparity gem isn't
|
|
616
|
+
installed under. The version manager's shim fails before fp starts, so fp can't diagnose
|
|
617
|
+
it from inside. Install the gem under the pinned Ruby by running `gem install featureparity`
|
|
618
|
+
inside the repo (`mise exec -- gem install featureparity` with mise), or put the bin
|
|
619
|
+
directory of the Ruby that has it first on `PATH`. `fp doctor`, run from anywhere fp
|
|
620
|
+
works, prints the exact commands.
|
|
621
|
+
- **The tests need a database.** `fp doctor` says whether they do (pg or mysql gems,
|
|
622
|
+
`config/database.yml`, docker-compose) and whether a `.devcontainer` can provide one. The
|
|
623
|
+
generated CI workflow has no database service, so add one to its report job.
|
|
624
|
+
- **The runner can't write JUnit without a new dependency.** RSpec's own
|
|
625
|
+
`--format json --out rspec.json` report is accepted anywhere `--junit` is, and `fp run`
|
|
626
|
+
adds the formatter for rspec, pytest, vitest and playwright itself.
|
|
627
|
+
<!-- fp-shared:end troubleshooting -->
|
|
628
|
+
|
|
498
629
|
## Quick reference
|
|
499
630
|
|
|
500
631
|
| Task | Command |
|
|
501
632
|
|------|---------|
|
|
633
|
+
| Check fp, config and the repo | `fp doctor` |
|
|
634
|
+
| Suggest slug, surfaces, test commands | `fp init --detect` |
|
|
502
635
|
| Onboard a repo | `fp init --project X` |
|
|
503
636
|
| List requirements | `fp list --project X` |
|
|
504
637
|
| Show gaps | `fp list --project X --gaps` |
|
|
638
|
+
| Draft coverage | `fp coverage --project X` |
|
|
505
639
|
| Show details | `fp show <slug> --project X` |
|
|
506
640
|
| Report evidence | `fp report <slug> --project X --surface Y --file Z --repo A/B` |
|
|
507
|
-
| Report from JUnit | `fp report --junit file.xml --project X --surface Y --repo A/B` |
|
|
641
|
+
| Report from JUnit / RSpec JSON | `fp report --junit file.xml --project X --surface Y --repo A/B` |
|
|
642
|
+
| Upload a run's screenshots/videos (optional, with permission) | `fp report --junit results.xml ... --attach-media` |
|
|
643
|
+
| Attach a test's capture (optional, with permission) | `fp attach <slug> <file> --project X --surface Y --example-title "<test name>"` |
|
|
644
|
+
| Run tests and report | `fp run --surface Y --repo A/B -- bundle exec rspec` |
|
|
508
645
|
| Propose requirement | `fp propose --project X --slug Y --name "..."` |
|
|
509
646
|
| Propose a change | `fp propose-change <slug> --project X --why "..." --reason "..."` |
|
|
510
647
|
| Propose a deletion | `fp propose-change <slug> --project X --removal --reason "..."` |
|
|
511
648
|
| View change history | `fp history <slug> --project X` |
|
|
649
|
+
| Ask a human about a draft | `fp question <slug> "..." --project X` |
|
|
650
|
+
| Read a draft's questions and answers | `fp questions <slug> --project X` |
|
|
512
651
|
| Triage requirement quality | `fp analyze --project X` |
|
|
513
652
|
| View work-item activity | `fp changes --project X --source-url URL` |
|
|
514
653
|
| Enforce parity | `fp check --project X` |
|