You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: .opencode/agents/product-owner.md
+1-2Lines changed: 1 addition & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -33,7 +33,6 @@ Load `skill session-workflow` first — it reads TODO.md, orients you to the cur
33
33
- You are the **sole owner** of `.feature` files and `docs/features/discovery.md`
34
34
- No other agent may edit these files
35
35
- Software-engineer escalates spec gaps to you; you decide whether to extend criteria
36
-
-**You pick** the next feature from backlog — the software-engineer never self-selects
37
36
-**NEVER move a feature to `in-progress/` unless its discovery section has `Status: BASELINED`** — if not baselined, complete Step 1 (Phase 2 + 3 + 4) first
38
37
39
38
## Step 5 — Accept
@@ -60,4 +59,4 @@ When a gap is reported (by software-engineer or reviewer):
60
59
61
60
-`session-workflow` — session start/end protocol
62
61
-`feature-selection` — when TODO.md is idle: score and select next backlog feature using WSJF
2.**One @id green** — the specific test under work passes, plus `test-fast` still passes
20
20
3.**Commit** — when a meaningful increment is green
21
21
4.**Quality tooling** — `lint`, `static-check`, full `test` with coverage run at end-of-feature handoff
22
22
23
-
Design correctness is far more important than lint/pyright/coverage compliance. Never run lint, static-check, or coverage during the TDD loop — those are handoff-only checks.
23
+
Design correctness is far more important than lint/pyright/coverage compliance. Never run lint (ruff check, ruff format), static-check (pyright), or coverage during the TDD loop — those are handoff-only checks.
24
24
25
25
---
26
26
@@ -37,7 +37,7 @@ Design correctness is far more important than lint/pyright/coverage compliance.
-[ ] Exactly one .feature `in_progress`. If not present, Load `skill feature-selection`
156
157
-[ ] Architecture stubs present in `<package>/` (committed by Step 2)
157
-
-[ ] Read all `docs/architecture/adr-NNN-*.md` files — understand the architectural decisions before writing any test
158
-
-[ ] Test stub files exist in `tests/features/<feature-name>/` — one file per `Rule:` block, all `@id` functions present with `@pytest.mark.skip`; if missing, write them now before entering RED
158
+
-[ ] Read all `docs/architecture/adr.md` files — understand the architectural decisions before writing any test
159
+
-[ ] Test stub files exist in `tests/features/<feature-name>/<rule_slug>_test.py` — one file per `Rule:` block, all `@id` stub functions present with `@pytest.mark.skip`; if missing, write them now before entering RED
159
160
160
161
### Write Test Stubs (if not present)
161
162
162
-
For each `Rule:` block in the in-progress `.feature` file, create `tests/features/<feature-name>/<rule-slug>_test.py` if it does not already exist. Write one function per `@id` Example, all skipped:
163
+
For each `Rule:` block in the in-progress `.feature` file, create `tests/features/<feature-name>/<rule_slug>_test.py` if it does not already exist. Write one function per `@id` Example, all skipped:
163
164
164
165
```python
165
166
@pytest.mark.skip(reason="not yet implemented")
166
-
def test_<rule_slug>_<8char_hex>() ->None:
167
+
def test_<feature_slug>_<@id>() ->None:
167
168
"""
168
-
Given: ...
169
-
When: ...
170
-
Then: ...
169
+
<@id steps raw text including new lines>
171
170
"""
172
-
# Given
173
-
# When
174
-
# Then
175
171
```
176
172
177
173
Run `uv run task gen-todo` after writing stubs to sync `@id` rows into `TODO.md`.
@@ -192,17 +188,17 @@ For each pending `@id`:
192
188
```
193
189
INNER LOOP
194
190
├── RED
195
-
│ ├── Confirm stub for this @id exists in tests/features/<feature-name>/ with @pytest.mark.skip
191
+
│ ├── Confirm stub for this @id exists in tests/features/<feature-name>/<rule_slug>.feature with @pytest.mark.skip
196
192
│ ├── Read existing stubs in `<package>/` — base the test on the current data model and signatures
197
193
│ ├── Write test body (Given/When/Then → Arrange/Act/Assert); remove @pytest.mark.skip
198
-
│ ├── Update stub signatures as needed — edit the `.py` file directly
194
+
│ ├── Update <package> stub signatures as needed — edit the `.py` file directly
199
195
│ ├── uv run task test-fast
200
196
│ └── EXIT: this @id FAILS
201
197
│ (if it passes: test is wrong — fix it first)
202
198
│
203
199
├── GREEN
204
200
│ ├── Write minimum code — YAGNI + KISS only
205
-
│ │ (no DRY, SOLID, OC here — those belong in REFACTOR)
201
+
│ │ (no DRY, SOLID, OC, Docstring, type hint here — those belong in REFACTOR)
206
202
│ ├── uv run task test-fast
207
203
│ └── EXIT: this @id passes AND all prior tests pass
208
204
│ (fix implementation only; do not advance to next @id)
@@ -221,7 +217,7 @@ Commit when a meaningful increment is green
221
217
```bash
222
218
uv run task lint
223
219
uv run task static-check
224
-
uv run task test# coverage must be 100%
220
+
uv run task test-coverage# coverage must be 100%
225
221
timeout 10s uv run task run
226
222
```
227
223
@@ -231,7 +227,7 @@ All must pass before Self-Declaration.
231
227
232
228
### Self-Declaration (once, after all quality gates pass)
233
229
234
-
Write into `TODO.md` under a `## Self-Declaration`block:
230
+
Answer honestly the `## Self-Declaration`report:
235
231
236
232
```markdown
237
233
## Self-Declaration
@@ -256,6 +252,7 @@ As a software-engineer I declare:
256
252
* OC-7: ≤20 lines per function, ≤50 per class — AGREE/DISAGREE | longest: file:line
257
253
* OC-8: ≤2 instance variables per class (behavioural classes only; dataclasses, Pydantic models, value objects, and TypedDicts are exempt) — AGREE/DISAGREE | file:line
258
254
* OC-9: no getters/setters — AGREE/DISAGREE | file:line
255
+
* Patterns: I have no good reason to refactor parts of the code using OOP or Design Patterns — AGREE/DISAGREE | file:line
259
256
* Patterns: no creational smell — AGREE/DISAGREE | file:line
260
257
* Patterns: no structural smell — AGREE/DISAGREE | file:line
261
258
* Patterns: no behavioral smell — AGREE/DISAGREE | file:line
@@ -268,7 +265,7 @@ A `DISAGREE` answer is not automatic rejection — state the reason inline and f
268
265
269
266
Signal completion to the reviewer. Provide:
270
267
- Feature file path
271
-
- Self-Declaration from TODO.md
268
+
- Self-Declaration report
272
269
- Summary of what was implemented
273
270
274
271
---
@@ -278,40 +275,35 @@ Signal completion to the reviewer. Provide:
278
275
### Test File Layout
279
276
280
277
```
281
-
tests/features/<feature-name>/<rule-slug>_test.py
278
+
tests/features/<feature-name>/<rule_slug>_test.py
282
279
```
283
280
284
281
-`<feature-name>` = the `.feature` file stem
285
-
-`<rule-slug>` = the `Rule:` title slugified
282
+
-`<rule_slug>` = the `Rule:` title slugified
286
283
287
284
### Function Naming
288
285
289
286
```python
290
-
def test_<rule_slug>_<8char_hex>() ->None:
287
+
def test_<rule_slug>_<@id>() ->None:
291
288
```
292
289
293
290
-`rule_slug` = the `Rule:` title with spaces/hyphens replaced by underscores, lowercase
294
-
-`8char_hex` = the `@id` from the `Example:` block
291
+
-`@id` = the `@id` from the `Example:` block
295
292
296
293
### Docstring Format (mandatory)
297
294
298
295
New tests start as skipped stubs. Remove `@pytest.mark.skip` when implementing in the RED phase.
299
296
300
297
```python
301
298
@pytest.mark.skip(reason="not yet implemented")
302
-
deftest_wall_bounce_a3f2b1c4() -> None:
299
+
deftest_<feature_slug>_<@id>() ->None:
303
300
"""
304
-
Given: A ball moving upward reaches y=0
305
-
When: The physics engine processes the next frame
306
-
Then: The ball velocity y-component becomes positive
301
+
<@id steps raw text including new lines>
307
302
"""
308
-
# Given
309
-
# When
310
-
# Then
311
303
```
312
304
313
305
**Rules**:
314
-
- Docstring contains `Given:/When:/Then:` on separate indented lines
306
+
- Docstring contains `Gherkin steps` as raw text on separate indented lines
315
307
- No extra metadata in docstring — traceability comes from function name `@id` suffix
-`@pytest.mark.slow` is mandatory on every `@given`-decorated test
352
345
-`@example(...)` is optional but encouraged
353
-
-Never use Hypothesis for: I/O, side effects, network calls, database writes
346
+
-Do not use Hypothesis for: I/O, side effects, network calls, database writes
354
347
355
348
### Semantic Alignment Rule
356
349
357
-
The test's Given/When/Then must operate at the **same abstraction level** as the AC's Given/When/Then.
350
+
The test's Given/When/Then must operate at the **same abstraction level** as the AC's Steps.
358
351
359
352
| AC says | Test must do |
360
353
|---|---|
@@ -369,7 +362,7 @@ If testing through the real entry point is infeasible, escalate to PO to adjust
369
362
- No `isinstance()`, `type()`, or internal attribute (`_x`) checks in assertions
370
363
- One assertion concept per test (multiple `assert` ok if they verify the same thing)
371
364
- No `pytest.mark.xfail` without written justification
372
-
-`pytest.mark.skip` is only valid on stubs (`reason="not yet implemented"`) — remove it when implementing
365
+
-`pytest.mark.skip(reason="not yet implemented")` is only valid on stubs — remove it when implementing
373
366
- Test data embedded directly in the test, not loaded from external files
374
367
375
368
### Test Tool Decision
@@ -396,7 +389,7 @@ Extra tests in `tests/unit/` are allowed freely (coverage, edge cases, etc.) —
396
389
397
390
## Signature Design
398
391
399
-
Signatures are written during Step 2 (Architecture) and refined during Step 3 (RED). They live directly in the package `.py` files — never in the `.feature` file.
392
+
<package> signatures are written during Step 2 (Architecture) and refined during Step 3 (RED). They live directly in the package `.py` files — never in the `.feature` file.
400
393
401
394
Key rules:
402
395
- Bodies are always `...` in the architecture stub
-**Instance variables**: ≤ 2 per class *(exception: dataclasses, Pydantic models, value objects, and TypedDicts are exempt — they may carry as many fields as the domain requires)*
181
169
-**Semantic alignment**: tests must operate at the same abstraction level as the acceptance criteria they cover
182
-
-**Integration tests**: multi-component features require at least one test in `tests/features/` that exercises the public entry point end-to-end
183
170
184
171
### Software-Engineer Quality Gate Priority Order
185
172
186
173
During Step 3 (TDD Loop), correctness priorities are:
5.**Quality tooling** — `lint`, `static-check`, full `test` with coverage run only at software-engineer handoff (before Step 4)
193
179
194
180
Design correctness is far more important than lint/pyright/coverage compliance. A well-designed codebase with minor lint issues is better than a lint-clean codebase with poor design.
195
181
@@ -200,10 +186,6 @@ Design correctness is far more important than lint/pyright/coverage compliance.
200
186
- Both are required. All-green automated checks are necessary but not sufficient for APPROVED.
201
187
- Reviewer defaults to REJECTED unless correctness is proven.
202
188
203
-
## Deprecation Process
204
-
205
-
This template does not support deprecation. Criteria changes are handled by adding new Examples with new `@id` tags.
206
-
207
189
## Release Management
208
190
209
191
Version format: `v{major}.{minor}.{YYYYMMDD}`
@@ -212,13 +194,13 @@ Version format: `v{major}.{minor}.{YYYYMMDD}`
212
194
- Same-day second release: increment minor, keep same date
213
195
- Each release gets a unique adjective-animal name
214
196
215
-
Use `@software-engineer /skill git-release` for the full release process.
197
+
Use `@software-engineer /skill git-release` for the full release process. When requested by the stakeholder
216
198
217
199
## Session Management
218
200
219
201
Every session: load `skill session-workflow`. Read `TODO.md` first, update it at the end.
220
202
221
-
`TODO.md` is a session bookmark — not a project journal. See `docs/workflow.md` for the full structure including the Cycle State and Self-Declaration blocks used during Step 4.
203
+
`TODO.md` is a session bookmark — not a project journal. See `docs/workflow.md` for the full structure including the Cycle State and Self-Declaration blocks used during Step 3.
0 commit comments