Skip to content

Commit f4e2cdc

Browse files
committed
Refactor code structure for improved readability and maintainability
1 parent d3d7b25 commit f4e2cdc

File tree

31 files changed

+4538
-50
lines changed

31 files changed

+4538
-50
lines changed

AGENTS.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ When introducing new dependencies, prefer these unless compatibility requires a
153153
- Type check with `ty` — all code must pass `ty check` with zero errors.
154154
- Use Gherkin + `behave` for outer-loop acceptance tests.
155155
- Use `pytest` for inner-loop TDD — tests must pass before claiming completion.
156+
- Use Hypothesis under `tests/` when you need generated coverage for invariants; these tests must run through the normal `uv run pytest` path.
156157
- Use `pytest-benchmark` for performance-sensitive code.
157158
- Use `pytest-cov` to track test coverage.
158159

@@ -178,8 +179,12 @@ When fixing failures, identify root cause first, then apply idiomatic fixes inst
178179

179180
Use outside-in development for behavior changes:
180181

182+
- **Git Restrictions:** NEVER use `git worktree`. All code modifications MUST be made directly on the current branch in the existing working directory.
181183
- start with a failing Gherkin scenario under `features/`,
182184
- drive implementation with failing `pytest` tests,
185+
- keep example-based `pytest` tests as the default inner loop for named cases and edge cases,
186+
- add Hypothesis properties under `tests/` when the rule is an invariant instead of a single named example,
187+
- treat Atheris as conditional planning work rather than baseline template scaffolding,
183188
- keep step definitions thin and reuse Python domain modules.
184189

185190
After each feature or bug fix, run:
@@ -198,9 +203,14 @@ If any command fails, report the failure and do not claim completion.
198203

199204
- BDD scenarios: place Gherkin features under `features/` and step definitions under `features/steps/`.
200205
- Use BDD to define acceptance behavior first, then use `pytest` for the inner TDD loop.
206+
- Keep example-based and Hypothesis-based tests together under `tests/`; `just test` must exercise both without a separate property-test command.
201207
- Unit tests: place in `tests/` mirroring the source structure.
202208
- Integration tests: place in `tests/integration/`.
203-
- Performance tests: use `pytest-benchmark` with `@pytest.mark.benchmark`.
209+
- Fuzz tests: only plan or add Atheris when a module parses hostile text or binary input, decodes file or protocol formats, or wraps native extensions where crash resistance matters.
210+
- Fuzz workflow: when fuzzing is justified, keep the harness targeted to the affected module instead of adding a default workspace-wide fuzz command to every starter.
211+
- Performance tests: use `pytest-benchmark` with `@pytest.mark.benchmark` only for code with an explicit latency SLA, throughput target, or hot-path requirement.
212+
- Treat benchmark work as optional planning scope; keep the standard `pytest` loop as the default when no performance requirement exists.
213+
- For `/pb-plan` work, mark fuzzing as `conditional` or `N/A` unless the scope explicitly includes parser-like, protocol, binary-decoding, hostile-input, or native-extension-heavy code.
204214
- Add tests for behavioral changes and public API changes.
205215
- Use `pytest` fixtures for setup/teardown; avoid `setUp`/`tearDown` methods.
206216
- Use `pytest.raises` for exception testing; `pytest.approx` for floating-point comparisons.

README.md

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,18 @@ pb-spec follows a **harness-first** philosophy: reliability comes from process d
5050
- **Idempotent**: safe to re-run; use `--force` to overwrite existing files
5151
- **Built with**: Python 3.12+, [click](https://click.palletsprojects.com/), [uv](https://docs.astral.sh/uv/)
5252

53+
## Project Layers
54+
55+
pb-spec is organized into three layers:
56+
57+
| Layer | Role | Artifacts |
58+
|-------|------|-----------|
59+
| **Workflow** | Agent-driven development lifecycle | `/pb-init``/pb-plan``/pb-refine``/pb-build` |
60+
| **Contract** | Machine-readable artifact specification | `design.md` + `tasks.md` + `features/*.feature` |
61+
| **Tooling** | Validation, parsing, and CI integration | `pb-spec validate`, internal parsers, future ecosystem tools |
62+
63+
The **workflow layer** defines the four commands and their execution semantics. The **contract layer** carries the explicit field requirements, state transitions, and scenario coverage rules described in [docs/contract.md](docs/contract.md). The **tooling layer** makes the contract executable through validation commands and reusable parsing libraries.
64+
5365
## Installation
5466

5567
```bash
@@ -111,6 +123,12 @@ pb-spec update
111123

112124
Update pb-spec to the latest version (requires `uv`).
113125

126+
```text
127+
pb-spec validate <target>
128+
```
129+
130+
Validate either a generated spec directory or a markdown feedback packet file. For spec directories, the current validator checks `design.md` required sections, `tasks.md` task blocks for required fields, allowed status values, and `DONE` completion evidence, inventories `features/*.feature` scenario names, and verifies `Scenario Coverage` references for `BDD+TDD` tasks. It does not currently fail build eligibility on an otherwise valid spec just because an extra scenario is not yet referenced by a task. For feedback files, it validates `🛑 Build Blocked` and `🔄 Design Change Request` packet completeness and requires concrete failure evidence rather than generic summaries.
131+
114132
## Workflow
115133

116134
four agent skills that chain together:
@@ -176,7 +194,7 @@ Reads `specs/<YYYY-MM-DD-NO-feature-name>/tasks.md` and implements each task seq
176194

177195
`/pb-build` is now explicitly architecture-bound: it reads the repo's **Architecture Decision Snapshot**, follows the feature's **Architecture Decisions**, re-checks **SRP** and **DIP** during execution, and keeps external dependencies behind interfaces or abstract classes when the design requires that seam. It should not improvise a different Factory, Strategy, Observer, Adapter, or Decorator choice mid-build.
178196

179-
Before parsing tasks or spawning subagents, `/pb-build` now runs a mandatory Phase 0 validation gate against the existing markdown contract: required design sections, required `Task X.Y` fields, and at least one feature scenario. If any item is missing, the build stops before implementation work starts. Task closure also follows explicit state transitions, so `DONE` is only reachable after scenario, test, and verification evidence are satisfied.
197+
Before parsing tasks or spawning subagents, `/pb-build` now runs a mandatory Phase 0 validation gate against the existing markdown contract: required design sections, required `Task X.Y` fields, and at least one feature scenario. If any item is missing, the build stops before implementation work starts. The builder still manages explicit task-state transitions during execution, while the current static validator focuses on allowed status values and evidence-backed completion gates rather than reconstructing prior state history from a single markdown snapshot.
180198

181199
## Skills Overview
182200

@@ -212,6 +230,45 @@ pb-spec's prompt design is inspired by Anthropic's research on [Effective Harnes
212230
- **Orchestrator (Builder):** `pb-build` SKILL enforces context hygiene, runtime verification gates, bounded retries, and DCR escalation
213231
- **Foundation (Init):** `pb-init` updates only the managed marker block in `AGENTS.md`, preserving all external user-authored constraints
214232

233+
## Library API
234+
235+
The validation module is importable for CI pipelines and tooling integration:
236+
237+
```python
238+
from pathlib import Path
239+
from pb_spec.validation import (
240+
validate_design_file,
241+
validate_task_file,
242+
collect_feature_scenarios,
243+
parse_task_blocks,
244+
parse_feedback_packets,
245+
validate_feedback_file,
246+
)
247+
248+
spec_dir = Path("specs/my-feature")
249+
250+
# Validate design.md sections
251+
errors = validate_design_file(spec_dir / "design.md")
252+
253+
# Validate tasks.md with scenario cross-referencing
254+
scenario_inventory = collect_feature_scenarios(spec_dir / "features")
255+
errors.extend(validate_task_file(spec_dir / "tasks.md", scenario_inventory=scenario_inventory))
256+
257+
# Parse task blocks programmatically
258+
task_blocks = parse_task_blocks(spec_dir / "tasks.md")
259+
for block in task_blocks:
260+
print(block.task_id, block.name, block.fields.get("Status"))
261+
262+
# Validate feedback packets
263+
errors = validate_feedback_file(Path("feedback.md"))
264+
```
265+
266+
CI usage with the CLI:
267+
268+
```bash
269+
pb-spec validate specs/my-feature && echo "Build eligible" || echo "Validation failed"
270+
```
271+
215272
## Development
216273

217274
```bash

0 commit comments

Comments
 (0)