featureparity 0.0.27 → 0.0.29
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 +14 -2
- data/lib/fp/client.rb +79 -2
- data/lib/fp/commands/analyze.rb +17 -0
- data/lib/fp/commands/base.rb +16 -0
- data/lib/fp/commands/check.rb +38 -4
- data/lib/fp/commands/ci_report.rb +2 -2
- data/lib/fp/commands/comment.rb +1 -1
- data/lib/fp/commands/comments.rb +146 -0
- data/lib/fp/commands/coverage.rb +149 -0
- data/lib/fp/commands/doctor.rb +228 -0
- data/lib/fp/commands/help.rb +41 -1
- data/lib/fp/commands/history.rb +16 -1
- data/lib/fp/commands/init.rb +181 -117
- data/lib/fp/commands/list.rb +58 -4
- data/lib/fp/commands/mark.rb +167 -0
- data/lib/fp/commands/projects.rb +6 -1
- data/lib/fp/commands/propose.rb +435 -53
- data/lib/fp/commands/propose_change.rb +13 -7
- data/lib/fp/commands/question.rb +137 -0
- data/lib/fp/commands/report.rb +40 -4
- data/lib/fp/commands/run.rb +147 -0
- data/lib/fp/commands/show.rb +41 -3
- data/lib/fp/commands/spot_check.rb +458 -0
- data/lib/fp/commands/tutorial.rb +95 -0
- data/lib/fp/commands/whoami.rb +2 -0
- data/lib/fp/commands.rb +8 -0
- data/lib/fp/config.rb +12 -0
- data/lib/fp/junit.rb +74 -11
- 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/tutorial/hexhaven/AGENTS.md +5 -0
- data/lib/fp/tutorial/hexhaven/README.md +29 -0
- data/lib/fp/tutorial/hexhaven/lib/hexhaven.rb +36 -0
- data/lib/fp/tutorial/hexhaven/test/junit_reporter.rb +134 -0
- data/lib/fp/tutorial/hexhaven/test/rules_test.rb +36 -0
- data/lib/fp/tutorial/hexhaven/test/test_helper.rb +6 -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 +304 -3
- metadata +19 -2
data/skills/fp/references/cli.md
CHANGED
|
@@ -210,17 +210,74 @@ fp report --junit junit.xml \
|
|
|
210
210
|
|
|
211
211
|
| Flag | Required | Description |
|
|
212
212
|
|------|----------|-------------|
|
|
213
|
-
| `--junit` | Yes | Path to JUnit XML report |
|
|
213
|
+
| `--junit` | Yes | Path to a JUnit XML report, or RSpec's own `--format json` report |
|
|
214
214
|
| `--project` | Yes | Project slug |
|
|
215
215
|
| `--surface` | Conditional | Default surface for markers without `@suffix`. Required if any matched marker pins no surface. |
|
|
216
216
|
| `--repo` | Yes | GitHub repo as `org/repo` |
|
|
217
217
|
| `--base-dir` | No | Where to resolve relative file paths (defaults to cwd) |
|
|
218
|
+
| `--attach-media` | No | Upload the screenshots and videos the run recorded (Playwright's `[[ATTACHMENT|…]]` entries) as visual evidence, one set per bound test, titled with the test's name. Unknown slugs and unsupported or oversized files are skipped with a reason |
|
|
218
219
|
|
|
219
220
|
In JUnit mode:
|
|
220
221
|
- Slugs come from `fp:<slug>` markers in the test files referenced by the report
|
|
221
222
|
- A marker binds to the test directly below it
|
|
222
223
|
- Skipped/pending tests become `stub`; all others `present`
|
|
223
224
|
- Unknown slugs and unmarked tests are skipped with a warning
|
|
225
|
+
- A JSON report from `rspec --format json --out rspec.json` works as-is (recognised by its
|
|
226
|
+
content, no extra flag), so an RSpec suite needs no `rspec_junit_formatter`. `fp ci-report`
|
|
227
|
+
and `fp check --junit` take it the same way.
|
|
228
|
+
|
|
229
|
+
### fp run
|
|
230
|
+
|
|
231
|
+
Run a test command with a report formatter fp adds itself, then report the results exactly
|
|
232
|
+
as `fp report --junit` would. Nothing is added to the project under test.
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
fp run --surface api --repo stowzilla/marketplace -- bundle exec rspec
|
|
236
|
+
fp run --surface api --repo stowzilla/marketplace -- pytest tests/
|
|
237
|
+
(cd frontend && fp run --surface web --repo stowzilla/marketplace -- npx vitest run)
|
|
238
|
+
fp run --surface web --repo stowzilla/marketplace -- npx playwright test
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
| Runner | What fp adds |
|
|
242
|
+
|--------|--------------|
|
|
243
|
+
| rspec | `--format json --out <tmp>`, plus `--format progress` when the command names no formatter |
|
|
244
|
+
| pytest | `-o junit_family=xunit1 --junitxml=<tmp>` (xunit1 carries each test's file and line) |
|
|
245
|
+
| vitest | `--reporter=default --reporter=junit --outputFile.junit=<tmp>` |
|
|
246
|
+
| playwright | `--reporter=list,junit`, with `PLAYWRIGHT_JUNIT_OUTPUT_NAME=<tmp>` |
|
|
247
|
+
|
|
248
|
+
Everything before `--` is an `fp report` flag (`--surface`, `--repo`, `--project`,
|
|
249
|
+
`--test-type`, `--work-item`, `--pr`, `--base-dir`, ...); everything after it is the test
|
|
250
|
+
command, left alone (global flags like `--json` or `-p` there belong to the runner). Agents
|
|
251
|
+
still report `present`/`stub` only. When the tests fail, fp reports first and then exits with
|
|
252
|
+
the test command's status. Any other runner errors with the supported list: make it write
|
|
253
|
+
JUnit XML and use `fp report --junit <file>`.
|
|
254
|
+
|
|
255
|
+
### fp attach / fp attachments
|
|
256
|
+
|
|
257
|
+
Attach a screenshot, video or file to a requirement as evidence. Visual captures sit under the
|
|
258
|
+
receipt of the test they prove on the requirement page, and the team can copy one into the
|
|
259
|
+
client showroom. This is optional and stores the file in FeatureParity, so an agent uploads
|
|
260
|
+
only with permission from the person it works for, and never captures someone's own screen.
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
fp attach checkout_flow e2e/results/checkout.webm --project stowzilla --surface web \
|
|
264
|
+
--example-title "pays by card" --sha $(git rev-parse HEAD)
|
|
265
|
+
fp attachments checkout_flow --project stowzilla # list
|
|
266
|
+
fp attachments checkout_flow <id> --project stowzilla # download URL
|
|
267
|
+
fp attach rm checkout_flow <id> --project stowzilla # delete
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
| Flag | Required | Description |
|
|
271
|
+
|------|----------|-------------|
|
|
272
|
+
| `--surface` | For images/videos | Surface the capture is for |
|
|
273
|
+
| `--example-title` | No | Name of the test this capture proves (nests it under that receipt) |
|
|
274
|
+
| `--evidence-key` | No | Bind to a specific receipt (`surface:repo:test_type`) |
|
|
275
|
+
| `--deployment-url` / `--deployed-at` | No | The deployment the capture observed |
|
|
276
|
+
| `--captured-at` / `--sha` / `--test-run-url` | No | When, at which commit, and in which run |
|
|
277
|
+
|
|
278
|
+
Images and video: png, jpg, gif, webp, mp4, webm, mov. Files: txt, md, json, svg, pdf. Up to
|
|
279
|
+
100 MB each, and several files per call. For a Playwright run, `fp report --junit ... --attach-media`
|
|
280
|
+
does this for every bound test at once (with the same permission). A capture never changes a cell's state.
|
|
224
281
|
|
|
225
282
|
### fp propose
|
|
226
283
|
|
|
@@ -265,6 +322,20 @@ fp propose --project stowzilla \
|
|
|
265
322
|
| `--why` | No | User need, problem or risk, and valuable outcome |
|
|
266
323
|
| `--required` | No | Comma-separated surfaces that must implement this |
|
|
267
324
|
| `--acceptance` | No | Observable behaviour and material boundaries |
|
|
325
|
+
| `--required-types` | No | Comma-separated kinds of test each surface needs |
|
|
326
|
+
| `--parent` | No | Parent requirement's slug (nests one level) |
|
|
327
|
+
| `--category` | No | `functional`, `non-functional`, `ux`, `performance`, `security`, `compliance` |
|
|
328
|
+
| `--tags` | No | Comma-separated labels |
|
|
329
|
+
| `--source-type` / `--source-url` / `--source-context` | No | Where it came from |
|
|
330
|
+
| `--source-ref` | No | A repository place it was read from, e.g. `app/models/order.rb:42`. Repeatable |
|
|
331
|
+
| `--dry-run` | No | Validate and lint the wording, and check the catalog for a taken slug or missing parent. Writes nothing |
|
|
332
|
+
| `--file` | No | YAML or JSON batch (below). Other flags become defaults for every entry |
|
|
333
|
+
|
|
334
|
+
After creating the draft, `fp propose` prints its quality feedback — a verdict, the issues
|
|
335
|
+
found, and suggestions — in the same run (`analysis` in `--json`). Act on it: revise a weak
|
|
336
|
+
draft with `fp propose-change`, or withdraw one that shouldn't be a requirement. When analysis
|
|
337
|
+
is unavailable the draft is still created, and the output says the feedback couldn't be
|
|
338
|
+
produced (`analysis_error`).
|
|
268
339
|
|
|
269
340
|
**Write for a decision-maker, not an implementer.** The result should sound natural and be
|
|
270
341
|
ready for management review without someone translating AI boilerplate or reverse-engineering
|
|
@@ -300,6 +371,53 @@ earn its place?
|
|
|
300
371
|
|
|
301
372
|
**Agents always create requirements as draft.** A human must activate them in the web app.
|
|
302
373
|
|
|
374
|
+
#### Checking wording first: `--dry-run`
|
|
375
|
+
|
|
376
|
+
`fp propose ... --dry-run` prints what would be created and a list of wording notes. These
|
|
377
|
+
cover a title that names the work (`Implement…`), commentary openings (`This feature…`,
|
|
378
|
+
`Users should be able to…`), filler (`seamless`, `robust`), a missing why or acceptance, an
|
|
379
|
+
acceptance with no `Example:`, several sentences of rule that may be separate promises, and a
|
|
380
|
+
number in the rule that a source has to have decided. Notes are advice, not errors. A taken
|
|
381
|
+
slug or a missing parent is an error, and it exits 1. Without `--dry-run`, the notes go to
|
|
382
|
+
stderr and the draft is still created.
|
|
383
|
+
|
|
384
|
+
#### A batch: `--file`
|
|
385
|
+
|
|
386
|
+
```yaml
|
|
387
|
+
defaults: # optional; merged into every entry
|
|
388
|
+
required: [api, web]
|
|
389
|
+
source_type: repo_scan
|
|
390
|
+
requirements:
|
|
391
|
+
- slug: profile_editing
|
|
392
|
+
name: People keep their profile current
|
|
393
|
+
why: ...
|
|
394
|
+
acceptance: "... Example: ..."
|
|
395
|
+
- slug: profile_required_fields
|
|
396
|
+
parent: profile_editing # another entry, or a requirement already in the project
|
|
397
|
+
name: A profile can't be saved without a school
|
|
398
|
+
source_refs: [app/models/academic_experience.rb:12]
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
Every entry is checked before anything is written: an unknown field (a typo like
|
|
402
|
+
`acceptence`), a bad category or source type, a slug that appears twice or already exists, and
|
|
403
|
+
a parent that isn't found or is itself a child. If any of these fails, nothing is created.
|
|
404
|
+
Parents in the file are created before their children, and the created drafts are printed as
|
|
405
|
+
one table. Run with `--dry-run` first to hand a human the batch for review.
|
|
406
|
+
|
|
407
|
+
### fp mark
|
|
408
|
+
|
|
409
|
+
```bash
|
|
410
|
+
fp mark academic_experience_required_fields spec/models/academic_experience_spec.rb:52
|
|
411
|
+
fp mark checkout_flow e2e/checkout.spec.ts:10 --surface web --type e2e
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
Inserts `fp:<slug>` (with `@surfaces` and `:type` when given) directly above the test on that
|
|
415
|
+
line, using the file's own comment syntax (`#`, `//` or `--`) and indentation, then names the
|
|
416
|
+
test it binds to. Running it again on the same marker changes nothing. `--comment` sets the
|
|
417
|
+
prefix for an extension fp doesn't know, and `--dry-run` shows the line without writing it.
|
|
418
|
+
This is purely local and needs no API key. Never mark a failing test to make a requirement
|
|
419
|
+
look covered.
|
|
420
|
+
|
|
303
421
|
### fp propose-change
|
|
304
422
|
|
|
305
423
|
Propose a change to a requirement that already exists — or propose deleting it.
|
|
@@ -332,9 +450,10 @@ fp propose-change print_container_qr --project stowzilla \
|
|
|
332
450
|
| `--parent` | No | Proposed parent requirement, by slug |
|
|
333
451
|
| `--slug` | No | Proposed new key; evidence follows it, but existing `fp:<slug>` markers must be updated |
|
|
334
452
|
| `--reason` | No | Why the change is needed |
|
|
335
|
-
| `--source-type` | No | `fizzy`, `discord`, `github_issue`, `jira`, `notion`, `manual`, `ai_chat` |
|
|
453
|
+
| `--source-type` | No | `fizzy`, `discord`, `github_issue`, `jira`, `notion`, `manual`, `ai_chat`, `repo_scan` (an agent derived it from the code) |
|
|
336
454
|
| `--source-url` | No | Link to the card/message/issue that prompted it |
|
|
337
455
|
| `--source-context` | No | Free-text context |
|
|
456
|
+
| `--source-ref` | No | A repository place that prompted it, e.g. `app/models/order.rb:42`. Repeatable |
|
|
338
457
|
|
|
339
458
|
At least one proposed value (or `--removal`) is required — a bare invocation would knock a
|
|
340
459
|
live requirement back to draft for nothing, so it errors instead.
|
|
@@ -370,6 +489,54 @@ the review decision where one was made. An open proposal is called out at the en
|
|
|
370
489
|
|
|
371
490
|
`--project` is optional when the repo has a `.featureparity.yml`.
|
|
372
491
|
|
|
492
|
+
### fp question / fp questions
|
|
493
|
+
|
|
494
|
+
Attach an open question for a human to the requirement it concerns, and read the answers.
|
|
495
|
+
Use it for the decisions a draft can't settle by itself, instead of leaving them in chat.
|
|
496
|
+
|
|
497
|
+
```bash
|
|
498
|
+
fp question upload_limits "Is the 5 MB cap per file or per upload?"
|
|
499
|
+
fp question upload_limits --body "Does the cap apply to admins?" --project stowzilla
|
|
500
|
+
fp questions upload_limits # every question, open and resolved, with answers
|
|
501
|
+
fp questions upload_limits --open --json # only the open ones
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
Asking never changes the requirement's status or wording. The human reviewing it sees the
|
|
505
|
+
question in Quick Review and on the requirement page, and answers it (the answer is kept
|
|
506
|
+
with the question) or dismisses it. `fp show <slug>` lists the open questions, and `fp
|
|
507
|
+
history` shows each question and its answer in the timeline. Agents can ask but cannot
|
|
508
|
+
answer or dismiss; there is no CLI command for that.
|
|
509
|
+
|
|
510
|
+
Draft and active requirements take questions, including a draft awaiting review of a
|
|
511
|
+
proposed change. Refusals, printed verbatim:
|
|
512
|
+
|
|
513
|
+
| Situation | Status |
|
|
514
|
+
|-----------|--------|
|
|
515
|
+
| No question text, or more than 2000 characters | 422 |
|
|
516
|
+
| Requirement is archived or rejected | 422 |
|
|
517
|
+
|
|
518
|
+
`--project` is optional when the repo has a `.featureparity.yml`.
|
|
519
|
+
### fp comments
|
|
520
|
+
|
|
521
|
+
Read or join the team's conversation on a requirement, and tag people or agents in it.
|
|
522
|
+
|
|
523
|
+
```bash
|
|
524
|
+
fp comments print_container_qr --project stowzilla # comments + who can be tagged
|
|
525
|
+
fp comments print_container_qr --body "The label redesign dropped this — retire it?" \
|
|
526
|
+
--tag andy@example.com
|
|
527
|
+
fp comments print_container_qr --body "Can you re-check this against the new label?" --tag claude
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
A comment never changes the requirement. `--tag` takes a teammate's email or name, or one of
|
|
531
|
+
the team's agents by name or key name; an unknown or ambiguous tag stops the command and
|
|
532
|
+
posts nothing. Tagged people get an email; each tagged agent fires the project's
|
|
533
|
+
`requirement.agent_mentioned` webhook, whose payload names the agent, the requirement and
|
|
534
|
+
the comment, plus the `fp` commands to read and answer it. If a human tagged you, answer
|
|
535
|
+
with `fp comments <slug> --body "..."` — and if the question means the requirement is
|
|
536
|
+
wrong, propose the change with `fp propose-change` rather than settling it in a comment.
|
|
537
|
+
|
|
538
|
+
`fp comment` (singular) is different: it threads a comment onto an open change proposal.
|
|
539
|
+
|
|
373
540
|
### fp analyze
|
|
374
541
|
|
|
375
542
|
Triage requirement quality: duplicates, fragments of a broader promise, vague wording,
|
|
@@ -459,6 +626,52 @@ classifications remain open for a human product decision. A stale candidate is r
|
|
|
459
626
|
later fingerprint always requires a new assessment. Assessing never changes the requirement
|
|
460
627
|
wording or CI outcome.
|
|
461
628
|
|
|
629
|
+
### fp spot-check
|
|
630
|
+
|
|
631
|
+
A random drug test for evidence. A green receipt proves a marked test ran and passed, not
|
|
632
|
+
that it checks what the requirement promises. `fp spot-check` picks one active requirement
|
|
633
|
+
that has evidence on record, at random, and prints its why and acceptance, its receipts, and
|
|
634
|
+
the source of every `fp:<slug>` test it finds in the checkout, then a brief.
|
|
635
|
+
|
|
636
|
+
```bash
|
|
637
|
+
fp spot-check # random pick; prints the seed
|
|
638
|
+
fp spot-check --seed 4821 # repeat that pick
|
|
639
|
+
fp spot-check --surface cli --json # narrow to one surface; machine-readable
|
|
640
|
+
fp spot-check print_container_qr print_label # chosen requirements, any status
|
|
641
|
+
fp spot-check --count 5 # five distinct requirements at random
|
|
642
|
+
fp spot-check --all # every active requirement with evidence
|
|
643
|
+
fp spot-check --test test/qr_test.rb # every marked test in the file
|
|
644
|
+
fp spot-check --test test/qr_test.rb:42 # only the test spanning that line
|
|
645
|
+
fp spot-check --path ../android # look for the tests in another checkout
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
Use one way of choosing per run: slugs, `--count`, `--all`, or `--test` (which may be
|
|
649
|
+
repeated). The seed is printed only for the random picks. In `--json` the result is
|
|
650
|
+
`checks` (one entry per requirement, each with `requirement`, `evidence` and `tests`), plus
|
|
651
|
+
a single `brief` that applies to every check.
|
|
652
|
+
|
|
653
|
+
`--prompt` prints the whole spot check as instructions for an agent, so a person or a
|
|
654
|
+
schedule can hand it over as is (`fp spot-check --count 3 --prompt | claude -p`). It ends
|
|
655
|
+
with what to report for each requirement: `proves`, `does_not_prove` or `uncertain`, the
|
|
656
|
+
clauses no assertion checks, the probe made and the tests that failed, and a clean
|
|
657
|
+
`git status`. It can't be combined with `--json`.
|
|
658
|
+
|
|
659
|
+
`--jev` first sends each requirement's marked tests (up to 10) to Jev and adds its read:
|
|
660
|
+
`agree`, `gaps` or `uncertain`, how likely the tests are to cover the acceptance, the
|
|
661
|
+
likeliest gap (`unasserted_clause`, `asserts_other_behaviour`, `cannot_fail`,
|
|
662
|
+
`tests_a_double`), and a per-test likelihood. Treat it as a hint about where to aim the
|
|
663
|
+
probe. It doesn't replace the probe. Jev is for paid plans: a person on Pro or Lifetime,
|
|
664
|
+
or a project whose owner is (that is what lets an agent use it). Otherwise the spot check
|
|
665
|
+
prints a note and carries on without it. Nothing Jev reads is stored.
|
|
666
|
+
|
|
667
|
+
The brief: list each result and boundary the acceptance promises; name the clause each
|
|
668
|
+
test's assertions actually check; make one small change to the *product code* that breaks
|
|
669
|
+
the promise, run only those tests, and confirm one fails; revert and confirm `git status` is
|
|
670
|
+
clean. A test that stays green under the probe, or checks something the acceptance doesn't
|
|
671
|
+
say, doesn't prove the requirement. Report that to a human with what you tried. Don't
|
|
672
|
+
rewrite the test or the requirement as part of a spot check. The command itself is
|
|
673
|
+
read-only.
|
|
674
|
+
|
|
462
675
|
#### Upgrading an existing project
|
|
463
676
|
|
|
464
677
|
Changed-test auditing requires fp 0.0.17 or newer and the corresponding backend deployment.
|
|
@@ -506,6 +719,45 @@ A slug suffixed with `✎` has a proposed change awaiting review — it is still
|
|
|
506
719
|
the gate, and its evidence is `suspect` until someone reviews the change. `--csv` writes
|
|
507
720
|
`<slug> (under review)` instead of the glyph.
|
|
508
721
|
|
|
722
|
+
`--status draft --gaps` lists *drafts* with a required surface lacking real evidence
|
|
723
|
+
(missing, stubbed, or failing). Plain `--gaps` reads the gate, which never measures a
|
|
724
|
+
never-approved draft, so on a freshly onboarded project it says "No gaps found". See
|
|
725
|
+
`fp coverage` for the full drafts × surfaces table.
|
|
726
|
+
|
|
727
|
+
### fp coverage
|
|
728
|
+
|
|
729
|
+
Draft coverage: which draft requirements have marked tests or evidence on which surfaces,
|
|
730
|
+
and which have none. The gate measures only active requirements (plus ones an open
|
|
731
|
+
proposal demoted), so on a new project where every requirement is still a draft `fp check`
|
|
732
|
+
says "Nothing to enforce yet". This is how an onboarding agent confirms its work before a
|
|
733
|
+
human activates anything.
|
|
734
|
+
|
|
735
|
+
```bash
|
|
736
|
+
fp coverage # drafts × surfaces, then the drafts with no evidence
|
|
737
|
+
fp coverage --surface api
|
|
738
|
+
fp coverage --all # also the measured (active / under review) rows
|
|
739
|
+
fp coverage --json # drafts, untested, and with --all, measured
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
| Flag | Description |
|
|
743
|
+
|------|-------------|
|
|
744
|
+
| `--project` | Project slug (optional if `.featureparity.yml` declares one) |
|
|
745
|
+
| `--surface` | Restrict to one surface |
|
|
746
|
+
| `--all` | Also list the requirements the gate measures |
|
|
747
|
+
|
|
748
|
+
Each cell is resolved from evidence exactly as the matrix will resolve it once the draft is
|
|
749
|
+
active. The command ends with a plain list — the "requirements with no test" section to hand
|
|
750
|
+
the human:
|
|
751
|
+
|
|
752
|
+
```
|
|
753
|
+
2 draft(s) with no evidence on a required surface:
|
|
754
|
+
export_csv — no evidence on: web
|
|
755
|
+
bulk_delete — no evidence on: api, web
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
"No evidence" means `missing`: nothing at all is filed, not even a stub. Drafts are
|
|
759
|
+
reported, never gated — this command exits 0 on a successful read, whatever it shows.
|
|
760
|
+
|
|
509
761
|
### fp check
|
|
510
762
|
|
|
511
763
|
The enforcement gate. Exits **1** when the project violates its enforcement level, so it
|
|
@@ -528,6 +780,7 @@ fp check --surface api --junit junit.xml # gate on this run's results (preview)
|
|
|
528
780
|
| `--junit` | Evaluate this run's JUnit results without saving them (repeatable) |
|
|
529
781
|
| `--pr [url]` | With `--junit`: this run is a pull request — fail only on parity it makes worse |
|
|
530
782
|
| `--warn-only` | Report violations but exit 0 |
|
|
783
|
+
| `--include-drafts` | After the verdict, print draft coverage (as `fp coverage`); never changes the exit code. `--json` adds `drafts` |
|
|
531
784
|
|
|
532
785
|
**Enforcement levels** (the level is configured on the project; don't hardcode one):
|
|
533
786
|
|
|
@@ -616,6 +869,8 @@ Onboard a repo onto FeatureParity. Writes three files and makes no API calls (so
|
|
|
616
869
|
before a key is configured).
|
|
617
870
|
|
|
618
871
|
```bash
|
|
872
|
+
fp init --detect # suggest slug, surfaces, test commands; writes nothing
|
|
873
|
+
fp init --detect --json
|
|
619
874
|
fp init --project stowzilla --surface api
|
|
620
875
|
fp init --project stowzilla --no-workflow # skip the CI workflow
|
|
621
876
|
fp init --project stowzilla --no-agents # skip the AGENTS.md section
|
|
@@ -635,7 +890,53 @@ marker comments and recognised on re-run, so it is never duplicated.
|
|
|
635
890
|
The `AGENTS.md` section tells agents to bind a test to a requirement with `fp:<slug>`, to
|
|
636
891
|
propose a new requirement when none covers the work, and to use `fp propose-change`
|
|
637
892
|
instead of editing or ignoring a requirement that no longer says the right thing — plus
|
|
638
|
-
the guards they would otherwise learn from a 403.
|
|
893
|
+
the guards they would otherwise learn from a 403. It opens with the fp version that wrote
|
|
894
|
+
it (`Written by fp X.Y.Z`), has an *Onboarding a repo* first-run path and a
|
|
895
|
+
*Troubleshooting* list, and copies its modeling, writing, onboarding and troubleshooting
|
|
896
|
+
blocks from the skill's `SKILL.md` (between `fp-shared` comments) rather than keeping a
|
|
897
|
+
second copy.
|
|
898
|
+
|
|
899
|
+
`--detect` reads the checkout (Gemfile, package.json, Podfile and Xcode projects, Android
|
|
900
|
+
manifests, pyproject/requirements, Rails routes and `config/database.yml`, docker-compose),
|
|
901
|
+
in the root and one directory down, and prints:
|
|
902
|
+
|
|
903
|
+
- a suggested slug (the git remote's repo name, else the directory name);
|
|
904
|
+
- suggested surfaces with the reason for each, and the rubric to judge them by: a surface is
|
|
905
|
+
somewhere a user interacts with the product, and an internal API with no separate client
|
|
906
|
+
isn't one;
|
|
907
|
+
- each test runner (rspec, minitest, jest, vitest, playwright, pytest, xctest, gradle), the
|
|
908
|
+
command that makes it write a report fp reads, the dependency that needs adding (or none),
|
|
909
|
+
and the `fp run` form where there is one;
|
|
910
|
+
- whether the tests need a database server, and whether there's a `.devcontainer`.
|
|
911
|
+
|
|
912
|
+
A plain `fp init` prints the detected test command and the database note in its closing
|
|
913
|
+
guidance. When the tests need a database server, the generated workflow's report recipe gets
|
|
914
|
+
a TODO and a commented-out service block. Committing the workflow before the `FP_API_KEY`
|
|
915
|
+
secret exists is fine: the gate skips with an explanation and stays green.
|
|
916
|
+
|
|
917
|
+
### fp doctor
|
|
918
|
+
|
|
919
|
+
Check that fp works here, with no API key and no API calls.
|
|
920
|
+
|
|
921
|
+
```bash
|
|
922
|
+
fp doctor
|
|
923
|
+
fp doctor --dir path/to/repo
|
|
924
|
+
fp doctor --json
|
|
925
|
+
```
|
|
926
|
+
|
|
927
|
+
- **Ruby:** the Ruby running fp, the gem's version and path, the `fp` on `PATH` (and whether
|
|
928
|
+
it's a version-manager shim), and whether this directory pins a different Ruby in
|
|
929
|
+
`.ruby-version`, `.tool-versions`, `mise.toml` or `.mise.toml`. On a mismatch it prints
|
|
930
|
+
the fix: install the gem under the pinned Ruby (`mise exec ruby@<pinned> -- gem install
|
|
931
|
+
featureparity`, or `gem install featureparity` in the repo), or put the running Ruby's bin
|
|
932
|
+
directory first on `PATH`.
|
|
933
|
+
- **Config:** the API environment (warning when it isn't production), whether a key is
|
|
934
|
+
present, which `.featureparity.yml` applies, and which fp wrote the `AGENTS.md` section.
|
|
935
|
+
- **Repo:** the same summary as `fp init --detect`.
|
|
936
|
+
|
|
937
|
+
`mise ERROR No version is set for shim: fp` comes from the shim, before fp runs, so doctor
|
|
938
|
+
can't catch it from inside that repo. Run it from somewhere fp works (another directory, or
|
|
939
|
+
with the other Ruby's bin directory on `PATH`) to get the commands.
|
|
639
940
|
|
|
640
941
|
### fp profile
|
|
641
942
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: featureparity
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.29
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stowzilla
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-11-
|
|
11
|
+
date: 2026-11-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: net-http
|
|
@@ -103,25 +103,33 @@ files:
|
|
|
103
103
|
- lib/fp/commands/check.rb
|
|
104
104
|
- lib/fp/commands/ci_report.rb
|
|
105
105
|
- lib/fp/commands/comment.rb
|
|
106
|
+
- lib/fp/commands/comments.rb
|
|
106
107
|
- lib/fp/commands/config_cmd.rb
|
|
107
108
|
- lib/fp/commands/conversation.rb
|
|
109
|
+
- lib/fp/commands/coverage.rb
|
|
110
|
+
- lib/fp/commands/doctor.rb
|
|
108
111
|
- lib/fp/commands/export.rb
|
|
109
112
|
- lib/fp/commands/help.rb
|
|
110
113
|
- lib/fp/commands/history.rb
|
|
111
114
|
- lib/fp/commands/init.rb
|
|
112
115
|
- lib/fp/commands/list.rb
|
|
116
|
+
- lib/fp/commands/mark.rb
|
|
113
117
|
- lib/fp/commands/matrix.rb
|
|
114
118
|
- lib/fp/commands/profile.rb
|
|
115
119
|
- lib/fp/commands/projects.rb
|
|
116
120
|
- lib/fp/commands/propose.rb
|
|
117
121
|
- lib/fp/commands/propose_change.rb
|
|
122
|
+
- lib/fp/commands/question.rb
|
|
118
123
|
- lib/fp/commands/report.rb
|
|
119
124
|
- lib/fp/commands/repos.rb
|
|
125
|
+
- lib/fp/commands/run.rb
|
|
120
126
|
- lib/fp/commands/setup.rb
|
|
121
127
|
- lib/fp/commands/show.rb
|
|
122
128
|
- lib/fp/commands/showroom.rb
|
|
123
129
|
- lib/fp/commands/showroom_media.rb
|
|
130
|
+
- lib/fp/commands/spot_check.rb
|
|
124
131
|
- lib/fp/commands/surfaces.rb
|
|
132
|
+
- lib/fp/commands/tutorial.rb
|
|
125
133
|
- lib/fp/commands/version.rb
|
|
126
134
|
- lib/fp/commands/whoami.rb
|
|
127
135
|
- lib/fp/config.rb
|
|
@@ -129,7 +137,16 @@ files:
|
|
|
129
137
|
- lib/fp/output.rb
|
|
130
138
|
- lib/fp/parity.rb
|
|
131
139
|
- lib/fp/project_config.rb
|
|
140
|
+
- lib/fp/repo_detector.rb
|
|
141
|
+
- lib/fp/requirement_lint.rb
|
|
142
|
+
- lib/fp/rspec_json.rb
|
|
132
143
|
- lib/fp/source_fingerprint.rb
|
|
144
|
+
- lib/fp/tutorial/hexhaven/AGENTS.md
|
|
145
|
+
- lib/fp/tutorial/hexhaven/README.md
|
|
146
|
+
- lib/fp/tutorial/hexhaven/lib/hexhaven.rb
|
|
147
|
+
- lib/fp/tutorial/hexhaven/test/junit_reporter.rb
|
|
148
|
+
- lib/fp/tutorial/hexhaven/test/rules_test.rb
|
|
149
|
+
- lib/fp/tutorial/hexhaven/test/test_helper.rb
|
|
133
150
|
- lib/fp/version.rb
|
|
134
151
|
- skills/fp/SKILL.md
|
|
135
152
|
- skills/fp/references/cli.md
|