featureparity 0.0.2 → 0.0.4

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.
@@ -0,0 +1,140 @@
1
+ ---
2
+ name: fp
3
+ description: "Use the fp CLI to track feature parity: report evidence linking tests to requirements, propose new requirements as drafts, view the parity matrix, and upload test results from JUnit XML when CI isn't available."
4
+ license: MIT
5
+ compatibility: Requires the fp executable on PATH (gem install featureparity)
6
+ metadata:
7
+ gem: featureparity
8
+ binary: fp
9
+ ---
10
+
11
+ # fp — FeatureParity CLI
12
+
13
+ Prefer the installed `fp` binary over inventing equivalent Ruby. Confirm it exists first:
14
+
15
+ ```bash
16
+ command -v fp && fp --version
17
+ ```
18
+
19
+ If missing: `gem install featureparity` (or `bundle exec fp` inside an app that already depends on the gem).
20
+
21
+ ## Non-interactive rules
22
+
23
+ - Always pass flags. Never rely on prompts or TTY menus.
24
+ - Use `--json` when parsing output programmatically.
25
+ - Use `fp help <command>` before destructive commands.
26
+ - Treat non-zero exit as failure; read stderr.
27
+
28
+ ## Authentication
29
+
30
+ `fp` needs an API key. Check if configured:
31
+
32
+ ```bash
33
+ # Environment variable (preferred for agents)
34
+ echo $FP_API_KEY
35
+
36
+ # Or via profile
37
+ fp profile list
38
+ ```
39
+
40
+ If not set, ask the user for their API key or have them run `fp setup`.
41
+
42
+ ## Core workflows
43
+
44
+ ### 1. Check existing requirements
45
+
46
+ ```bash
47
+ fp list --project stowzilla # All active requirements
48
+ fp list --project stowzilla --gaps # Requirements without evidence
49
+ fp show <slug> --project stowzilla # Requirement details
50
+ fp matrix --project stowzilla # ASCII parity matrix
51
+ fp matrix --project stowzilla --csv # Export as CSV
52
+ ```
53
+
54
+ ### 2. Add the fp:<slug> marker to tests
55
+
56
+ Place a comment immediately before the test to bind it to a requirement:
57
+
58
+ ```ruby
59
+ # fp:print_container_qr
60
+ it 'prints a QR code onto the container label' do
61
+ expect(label.qr_code).to be_present
62
+ end
63
+ ```
64
+
65
+ **Rules:**
66
+ - Use `fp:<slug>` where `<slug>` is the requirement's slug
67
+ - Keep test names human-readable — the marker handles binding
68
+ - Pin surfaces with `@suffix`: `fp:print_qr@api,web` reports for both surfaces
69
+
70
+ ### 3. Report evidence (single test)
71
+
72
+ ```bash
73
+ fp report <slug> \
74
+ --project stowzilla \
75
+ --surface api \
76
+ --file spec/qr_spec.rb \
77
+ --repo stowzilla/marketplace \
78
+ --work-item https://app.fizzy.do/123/cards/456
79
+ ```
80
+
81
+ **Required:** `<slug>`, `--project`, `--surface`, `--file`, `--repo`
82
+ **Optional:** `--pr`, `--sha`, `--work-item`, `--ci-url`, `--title`
83
+
84
+ **Agents report `present` (default) or `stub` only. Never `passing` or `failing`.**
85
+
86
+ ### 4. Report evidence from JUnit XML (batch upload without CI)
87
+
88
+ When CI isn't available, run the suite locally and upload the report:
89
+
90
+ ```bash
91
+ # 1. Generate JUnit XML
92
+ rspec --format RspecJunitFormatter --out junit.xml
93
+
94
+ # 2. Upload — one call covers every marked test
95
+ fp report --junit junit.xml \
96
+ --project stowzilla \
97
+ --surface api \
98
+ --repo stowzilla/marketplace \
99
+ --work-item https://app.fizzy.do/123/cards/456
100
+ ```
101
+
102
+ - No `<slug>` positional needed — slugs come from the `fp:<slug>` markers
103
+ - Skipped tests become `stub`; all others `present`
104
+ - Unknown slugs and unmarked tests are skipped with a warning
105
+ - `--surface` is the default; markers can override with `@suffix`
106
+ - `--base-dir DIR` sets where relative paths resolve from
107
+
108
+ ### 5. Propose new requirements
109
+
110
+ ```bash
111
+ fp propose --project stowzilla \
112
+ --slug print_container_qr \
113
+ --name "Print QR on container label" \
114
+ --why "Enables scanning containers in the warehouse" \
115
+ --required api,customer_android \
116
+ --acceptance "Label shows scannable QR code"
117
+ ```
118
+
119
+ **Agents always create requirements as draft.** A human must activate in the web app.
120
+
121
+ ## Quick reference
122
+
123
+ | Task | Command |
124
+ |------|---------|
125
+ | List requirements | `fp list --project X` |
126
+ | Show gaps | `fp list --project X --gaps` |
127
+ | Show details | `fp show <slug> --project X` |
128
+ | Report evidence | `fp report <slug> --project X --surface Y --file Z --repo A/B` |
129
+ | Report from JUnit | `fp report --junit file.xml --project X --surface Y --repo A/B` |
130
+ | Propose requirement | `fp propose --project X --slug Y --name "..."` |
131
+ | View matrix | `fp matrix --project X` |
132
+ | List surfaces | `fp surfaces --project X` |
133
+ | List projects | `fp projects` |
134
+
135
+ All commands support `--json` for machine-readable output.
136
+
137
+ ## When to read more
138
+
139
+ - Full flag reference and exit codes → `references/cli.md`
140
+ - Marker syntax and examples → `references/markers.md`
@@ -0,0 +1,245 @@
1
+ # fp CLI Reference
2
+
3
+ Complete flag reference for the `fp` command-line tool.
4
+
5
+ ## Global flags
6
+
7
+ These work with any command:
8
+
9
+ | Flag | Description |
10
+ |------|-------------|
11
+ | `--json` | Output JSON instead of human-readable text |
12
+ | `--profile NAME` | Use a named profile from `~/.config/fp/config.yml` |
13
+ | `--api-url URL` | Override the API URL for this invocation |
14
+ | `--help` | Show help for any command |
15
+
16
+ ## Commands
17
+
18
+ ### fp setup
19
+
20
+ Interactive first-run configuration. Validates API key and saves a profile.
21
+
22
+ ```bash
23
+ fp setup # Interactive
24
+ fp setup --api-key fp_... --non-interactive # Non-interactive
25
+ fp setup --api-key fp_... --profile ci # Named profile
26
+ ```
27
+
28
+ ### fp projects
29
+
30
+ List accessible projects.
31
+
32
+ ```bash
33
+ fp projects
34
+ fp projects --json
35
+ ```
36
+
37
+ ### fp surfaces
38
+
39
+ List surfaces for a project.
40
+
41
+ ```bash
42
+ fp surfaces --project stowzilla
43
+ fp surfaces --project stowzilla --json
44
+ ```
45
+
46
+ ### fp list
47
+
48
+ List requirements.
49
+
50
+ ```bash
51
+ fp list --project stowzilla # All active requirements
52
+ fp list --project stowzilla --gaps # Requirements without evidence
53
+ fp list --project stowzilla --status draft
54
+ fp list --project stowzilla --json
55
+ ```
56
+
57
+ | Flag | Description |
58
+ |------|-------------|
59
+ | `--project` | Project slug (required) |
60
+ | `--gaps` | Show only requirements without evidence |
61
+ | `--status` | Filter by status: active, draft, archived |
62
+ | `--category` | Filter by category |
63
+
64
+ ### fp show
65
+
66
+ Show requirement details.
67
+
68
+ ```bash
69
+ fp show print_container_qr --project stowzilla
70
+ fp show print_container_qr --project stowzilla --json
71
+ ```
72
+
73
+ ### fp report
74
+
75
+ Report evidence linking a test to a requirement.
76
+
77
+ **Single-slug mode:**
78
+
79
+ ```bash
80
+ fp report <slug> \
81
+ --project stowzilla \
82
+ --surface api \
83
+ --file spec/qr_spec.rb \
84
+ --repo stowzilla/marketplace \
85
+ [--pr URL] [--sha COMMIT] [--work-item URL] [--ci-url URL] [--title "..."] [--state present|stub]
86
+ ```
87
+
88
+ | Flag | Required | Description |
89
+ |------|----------|-------------|
90
+ | `<slug>` | Yes | Requirement slug (positional) |
91
+ | `--project` | Yes | Project slug |
92
+ | `--surface` | Yes | Surface this evidence covers |
93
+ | `--file` | Yes | Path to test file (relative to repo root) |
94
+ | `--repo` | Yes | GitHub repo as `org/repo` |
95
+ | `--pr` | No | Pull request URL |
96
+ | `--sha` | No | Commit SHA |
97
+ | `--work-item` | No | Fizzy card or issue URL |
98
+ | `--ci-url` | No | CI run URL |
99
+ | `--title` | No | Human-readable test name for display |
100
+ | `--state` | No | `present` (default) or `stub`. Never `passing`/`failing` — that's CI's job. |
101
+
102
+ **JUnit batch mode:**
103
+
104
+ ```bash
105
+ fp report --junit junit.xml \
106
+ --project stowzilla \
107
+ --surface api \
108
+ --repo stowzilla/marketplace \
109
+ [--base-dir DIR] [--pr URL] [--sha COMMIT] [--work-item URL] [--ci-url URL]
110
+ ```
111
+
112
+ | Flag | Required | Description |
113
+ |------|----------|-------------|
114
+ | `--junit` | Yes | Path to JUnit XML report |
115
+ | `--project` | Yes | Project slug |
116
+ | `--surface` | Conditional | Default surface for markers without `@suffix`. Required if any matched marker pins no surface. |
117
+ | `--repo` | Yes | GitHub repo as `org/repo` |
118
+ | `--base-dir` | No | Where to resolve relative file paths (defaults to cwd) |
119
+
120
+ In JUnit mode:
121
+ - Slugs come from `fp:<slug>` markers in the test files referenced by the report
122
+ - A marker binds to the test directly below it
123
+ - Skipped/pending tests become `stub`; all others `present`
124
+ - Unknown slugs and unmarked tests are skipped with a warning
125
+
126
+ ### fp propose
127
+
128
+ Propose a new requirement as draft.
129
+
130
+ ```bash
131
+ fp propose --project stowzilla \
132
+ --slug print_container_qr \
133
+ --name "Print QR on container label" \
134
+ --why "Enables scanning containers" \
135
+ --required api,customer_android \
136
+ --acceptance "Label shows scannable QR code"
137
+ ```
138
+
139
+ | Flag | Required | Description |
140
+ |------|----------|-------------|
141
+ | `--project` | Yes | Project slug |
142
+ | `--slug` | Yes | Requirement slug (immutable, choose carefully) |
143
+ | `--name` | Yes | Human-readable name |
144
+ | `--why` | No | Why this requirement matters |
145
+ | `--required` | No | Comma-separated surfaces that must implement this |
146
+ | `--acceptance` | No | How to verify completion |
147
+
148
+ **Agents always create requirements as draft.** A human must activate in the web app.
149
+
150
+ ### fp matrix
151
+
152
+ Display the parity matrix.
153
+
154
+ ```bash
155
+ fp matrix --project stowzilla # ASCII table
156
+ fp matrix --project stowzilla --csv # CSV export
157
+ fp matrix --project stowzilla --json # JSON
158
+ ```
159
+
160
+ ### fp profile
161
+
162
+ Manage named profiles. Each profile stores an API key and (optionally) the
163
+ API URL and environment it targets, so a key is always tagged with the
164
+ environment it talks to.
165
+
166
+ ```bash
167
+ fp profile list
168
+ fp profile add staging --api-key fp_... --api-url https://api.staging.featureparity.dev
169
+ fp profile add staging --api-key fp_... --environment staging
170
+ ```
171
+
172
+ If `--environment` is omitted it is derived from the API URL's host, following
173
+ the Belt DNS convention (`infrastructure/modules/app/dns.tf`):
174
+
175
+ - `api.featureparity.dev` → `production`
176
+ - `api.staging.featureparity.dev` → `staging`
177
+ - `api-abc-1234.dev.featureparity.dev` → `abc-1234` (nested/ephemeral env; `api-` prefix)
178
+ - `localhost` / `127.0.0.1` → `local`
179
+
180
+ `fp profile list` shows the tag.
181
+
182
+ ### fp config
183
+
184
+ Manage global settings.
185
+
186
+ ```bash
187
+ fp config list
188
+ fp config get api_url
189
+ fp config set api_url https://api.dev.featureparity.dev
190
+ fp config unset api_url
191
+ fp config whoami # alias of `fp whoami`
192
+ ```
193
+
194
+ ### fp whoami
195
+
196
+ Show the *resolved* configuration this invocation would use — the active
197
+ profile, the environment, the API URL (and where each value came from), and
198
+ whether an API key is present (masked, never the full token). Makes no API
199
+ calls, so it works even without a valid key.
200
+
201
+ ```bash
202
+ fp whoami
203
+ fp whoami --json
204
+ fp --profile staging whoami # inspect a specific profile
205
+ fp --api-url http://localhost:9292 whoami
206
+ ```
207
+
208
+ ### fp repos
209
+
210
+ Map surfaces to local repo paths (stored locally, not in the web app).
211
+
212
+ ```bash
213
+ fp repos list --project stowzilla
214
+ fp repos set customer_android ~/code/customer-android --project stowzilla --repo org/repo
215
+ fp repos get customer_android --project stowzilla
216
+ fp repos unset customer_android --project stowzilla
217
+ ```
218
+
219
+ ## Exit codes
220
+
221
+ | Code | Meaning |
222
+ |------|---------|
223
+ | 0 | Success |
224
+ | 1 | General error (invalid flags, missing required args, API error) |
225
+
226
+ ## Configuration files
227
+
228
+ - `~/.config/fp/config.yml` — Profiles and global settings
229
+ - `FP_API_KEY` environment variable overrides all profiles
230
+ - `FP_API_URL` environment variable overrides API URL
231
+ - `FP_PROFILE` environment variable selects a profile
232
+
233
+ ## API URL priority
234
+
235
+ 1. `--api-url` flag
236
+ 2. `FP_API_URL` environment variable
237
+ 3. Profile `api_url` setting
238
+ 4. Global `api_url` setting
239
+ 5. Default: `https://api.featureparity.dev`
240
+
241
+ ## Profile resolution priority
242
+
243
+ 1. `--profile` flag
244
+ 2. `FP_PROFILE` environment variable
245
+ 3. `default` profile (if it exists)
@@ -0,0 +1,149 @@
1
+ # fp Marker Syntax
2
+
3
+ The `fp:<slug>` marker binds a test to a FeatureParity requirement. Place it as a comment immediately before the test definition.
4
+
5
+ ## Basic syntax
6
+
7
+ ```
8
+ fp:<slug>
9
+ ```
10
+
11
+ Where `<slug>` is the requirement's slug (lowercase, underscores, e.g., `print_container_qr`).
12
+
13
+ ## Surface pinning
14
+
15
+ Pin one or more surfaces with the `@` suffix:
16
+
17
+ ```
18
+ fp:<slug>@<surface>
19
+ fp:<slug>@<surface1>,<surface2>
20
+ ```
21
+
22
+ Examples:
23
+ - `fp:print_qr` — uses `--surface` flag when reporting
24
+ - `fp:print_qr@api` — reports for `api` surface only
25
+ - `fp:print_qr@api,web` — reports for both `api` and `web`
26
+
27
+ When using `fp report --junit`, each pinned surface produces a separate evidence upload.
28
+
29
+ ## Language examples
30
+
31
+ ### Ruby/RSpec
32
+
33
+ ```ruby
34
+ # fp:print_container_qr
35
+ it 'prints a QR code onto the container label' do
36
+ expect(label.qr_code).to be_present
37
+ end
38
+
39
+ # fp:print_container_qr@api,web
40
+ it 'prints a QR code (backend test covering multiple surfaces)' do
41
+ expect(label.qr_code).to be_present
42
+ end
43
+ ```
44
+
45
+ ### Kotlin/JUnit
46
+
47
+ ```kotlin
48
+ // fp:print_container_qr
49
+ @Test
50
+ fun `prints a QR code onto the container label`() {
51
+ assertNotNull(label.qrCode)
52
+ }
53
+
54
+ // fp:print_container_qr@customer_android
55
+ @Test
56
+ fun `prints a QR code (Android-specific)`() {
57
+ assertNotNull(label.qrCode)
58
+ }
59
+ ```
60
+
61
+ ### Swift/XCTest
62
+
63
+ ```swift
64
+ // fp:print_container_qr
65
+ func testPrintsQRCodeOntoContainerLabel() {
66
+ XCTAssertNotNil(label.qrCode)
67
+ }
68
+
69
+ // fp:print_container_qr@customer_ios
70
+ func testPrintsQRCodeOniOS() {
71
+ XCTAssertNotNil(label.qrCode)
72
+ }
73
+ ```
74
+
75
+ ### TypeScript/Jest
76
+
77
+ ```typescript
78
+ // fp:print_container_qr
79
+ it('prints a QR code onto the container label', () => {
80
+ expect(label.qrCode).toBeDefined();
81
+ });
82
+
83
+ // fp:print_container_qr@web
84
+ it('prints a QR code (web-specific)', () => {
85
+ expect(label.qrCode).toBeDefined();
86
+ });
87
+ ```
88
+
89
+ ### Python/pytest
90
+
91
+ ```python
92
+ # fp:print_container_qr
93
+ def test_prints_qr_code_onto_container_label():
94
+ assert label.qr_code is not None
95
+
96
+ # fp:print_container_qr@api
97
+ def test_prints_qr_code_api():
98
+ assert label.qr_code is not None
99
+ ```
100
+
101
+ ### Go
102
+
103
+ ```go
104
+ // fp:print_container_qr
105
+ func TestPrintsQRCodeOntoContainerLabel(t *testing.T) {
106
+ if label.QRCode == nil {
107
+ t.Fatal("expected QR code")
108
+ }
109
+ }
110
+
111
+ // fp:print_container_qr@api
112
+ func TestPrintsQRCodeAPI(t *testing.T) {
113
+ if label.QRCode == nil {
114
+ t.Fatal("expected QR code")
115
+ }
116
+ }
117
+ ```
118
+
119
+ ## Rules
120
+
121
+ 1. **One marker per test.** A marker binds to the test directly below it.
122
+
123
+ 2. **Human-readable test names.** The marker handles binding; don't name tests after slugs.
124
+ - ❌ `it 'print_container_qr' do`
125
+ - ✅ `it 'prints a QR code onto the container label' do`
126
+
127
+ 3. **Marker must be immediately before the test.** No blank lines or other code between the marker comment and the test definition.
128
+
129
+ 4. **Comment style follows language conventions.** Use `#` for Ruby/Python, `//` for Kotlin/Swift/TypeScript/Go.
130
+
131
+ ## Verification
132
+
133
+ After adding a marker, verify it's findable:
134
+
135
+ ```bash
136
+ grep -r "fp:print_container_qr" spec/
137
+ ```
138
+
139
+ ## JUnit binding
140
+
141
+ When using `fp report --junit`, the CLI:
142
+
143
+ 1. Parses the JUnit XML report
144
+ 2. For each `<testcase>`, reads the `file` attribute to find the source file
145
+ 3. Scans the source file for `fp:<slug>` markers
146
+ 4. Binds each marker to the test directly below it
147
+ 5. Reports evidence for each binding
148
+
149
+ Testcases without a marker are skipped with a warning. Markers with unknown slugs are also skipped.
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.2
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stowzilla
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-08-25 00:00:00.000000000 Z
11
+ date: 2026-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: net-http
@@ -103,13 +103,19 @@ files:
103
103
  - lib/fp/commands/projects.rb
104
104
  - lib/fp/commands/propose.rb
105
105
  - lib/fp/commands/report.rb
106
+ - lib/fp/commands/repos.rb
106
107
  - lib/fp/commands/setup.rb
107
108
  - lib/fp/commands/show.rb
108
109
  - lib/fp/commands/surfaces.rb
109
110
  - lib/fp/commands/version.rb
111
+ - lib/fp/commands/whoami.rb
110
112
  - lib/fp/config.rb
113
+ - lib/fp/junit.rb
111
114
  - lib/fp/output.rb
112
115
  - lib/fp/version.rb
116
+ - skills/fp/SKILL.md
117
+ - skills/fp/references/cli.md
118
+ - skills/fp/references/markers.md
113
119
  homepage: https://featureparity.dev
114
120
  licenses:
115
121
  - MIT