diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 950b26e..6169589 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,6 +67,8 @@ jobs: fail-fast: false matrix: python-version: ["3.13"] + env: + UV_SYSTEM_PYTHON: "false" steps: - name: Checkout code @@ -80,8 +82,8 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install dependencies - run: uv sync --locked --all-extras --dev - + run: uv sync --locked --all-extras --dev && uv pip install -e . + - name: Run fast tests run: uv run task test-fast @@ -115,7 +117,9 @@ jobs: permissions: contents: read actions: read - + env: + UV_SYSTEM_PYTHON: "false" + steps: - name: Checkout code uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.1 @@ -130,7 +134,7 @@ jobs: run: uv python install 3.13 - name: Install dependencies - run: uv sync --locked --all-extras --dev + run: uv sync --locked --all-extras --dev && uv pip install -e . - name: Build documentation run: uv run task doc-build diff --git a/.github/workflows/tag-release.yml b/.github/workflows/tag-release.yml index 4fbc251..e7c4325 100644 --- a/.github/workflows/tag-release.yml +++ b/.github/workflows/tag-release.yml @@ -35,6 +35,25 @@ jobs: echo "exists=false" >> "$GITHUB_OUTPUT" fi + - name: Install uv + if: steps.check.outputs.exists == 'false' + uses: astral-sh/setup-uv@cdfb2ee6dde255817c739680168ad81e184c4bfb # v4.0.0 + with: + enable-cache: true + cache-dependency-glob: "uv.lock" + + - name: Set up Python 3.13 + if: steps.check.outputs.exists == 'false' + run: uv python install 3.13 + + - name: Install dependencies + if: steps.check.outputs.exists == 'false' + run: uv sync --locked --all-extras --dev + + - name: Run release-check + if: steps.check.outputs.exists == 'false' + run: uv run task release-check + - name: Create and push tag if: steps.check.outputs.exists == 'false' env: diff --git a/.opencode/agents/product-owner.md b/.opencode/agents/product-owner.md index a5ec440..3993111 100644 --- a/.opencode/agents/product-owner.md +++ b/.opencode/agents/product-owner.md @@ -45,8 +45,8 @@ After the system-architect approves (Step 4): 1. Run or observe the feature yourself. If user interaction is involved, interact with it. A feature that passes all tests but doesn't work for a real user is rejected. 2. Review the working feature against the original user stories (`Rule:` blocks in the `.feature` file). -3. **If accepted**: move `docs/features/in-progress/.feature` → `docs/features/completed/.feature`; update `WORK.md` (`@state: STEP-5-MERGE`, append to Session Log); notify stakeholder. The stakeholder decides when to trigger PR and release. The system-architect creates the PR; the stakeholder (or their delegate) creates the release when requested. -4. **If rejected**: write specific feedback in `WORK.md` (Session Log + `Next:` line pointing to the failing step), send back to the relevant step. +3. **If accepted**: move `docs/features/in-progress/.feature` → `docs/features/completed/.feature`; update `WORK.md` (`@state: STEP-5-MERGE`); notify stakeholder. The stakeholder decides when to trigger PR and release. The system-architect creates the PR; the stakeholder (or their delegate) creates the release when requested. +4. **If rejected**: write specific feedback in `WORK.md` pointing to the failing step, then send back to the relevant step. ## Handling Gaps @@ -64,7 +64,7 @@ When a gap is reported (by software-engineer or system-architect): When a defect is reported against any feature: 1. Add a `@bug` Example to the relevant `Rule:` block in the `.feature` file using the standard `Given/When/Then` format describing the correct behavior. -2. Update `WORK.md` Session Log to note the new bug Example; set `Next:` to `Run @software-engineer — implement @bug Example in `. +2. Update `WORK.md` `@state` to reflect the bug work and notify the software-engineer. 3. SE implements the test in `tests/features/` **and** a `@given` Hypothesis property test in `tests/unit/`. Both are required. ## Available Skills diff --git a/.opencode/agents/software-engineer.md b/.opencode/agents/software-engineer.md index a58a148..a4227f0 100644 --- a/.opencode/agents/software-engineer.md +++ b/.opencode/agents/software-engineer.md @@ -53,14 +53,14 @@ Load `skill run-session` first — it reads FLOW.md, orients you to the current If `docs/features/in-progress/` contains only `.gitkeep` (no `.feature` file): 1. Do not pick a feature from backlog yourself. -2. Update `WORK.md` `Next:` line: `Run @product-owner — load skill select-feature and pick the next BASELINED feature from backlog.` +2. Update `WORK.md` `@state` to `[IDLE]` if it is not already. 3. Stop. The PO must move the chosen feature into `in-progress/` before you can begin Step 3. ## Spec Gaps If during implementation you discover behavior not covered by existing acceptance criteria: - Do not extend criteria yourself — escalate to the PO -- Note the gap in `WORK.md` `Next:` line and Session Log +- Note the gap in `WORK.md` and escalate to PO ## Available Skills diff --git a/.opencode/agents/system-architect.md b/.opencode/agents/system-architect.md index 1457029..5e2a8bb 100644 --- a/.opencode/agents/system-architect.md +++ b/.opencode/agents/system-architect.md @@ -47,13 +47,13 @@ Load `skill run-session` first — it reads FLOW.md, orients you to the current - You own `docs/system.md` (including the `## Domain Model` section) and `docs/adr/ADR-*.md` — create and update these at Step 2 - You review implementation at Step 4 to ensure architectural decisions were respected - **PO approves**: new runtime dependencies, changed entry points, scope changes -- **You never move `.feature` files.** The PO is the sole owner of all feature file moves. If you find no `.feature` file in `docs/features/in-progress/`, **STOP** — do not self-select a feature. Update `WORK.md` `Next:` and escalate to PO. +- **You never move `.feature` files.** The PO is the sole owner of all feature file moves. If you find no `.feature` file in `docs/features/in-progress/`, **STOP** — do not self-select a feature. Update `WORK.md` `@state` to `[IDLE]` and escalate to PO. ## Step 2 → Step 3 Handoff After architecture is complete and test stubs are generated: 1. Commit all changes on `feat/` -2. Update `WORK.md`: set `@state: STEP-3-WORKING`, append to Session Log, set `Next: Run @software-engineer — Step 3 TDD Loop` +2. Update `WORK.md`: set `@state: STEP-3-WORKING` 3. Stop. The SE takes over for implementation. ## Step 4 Review Stance @@ -67,7 +67,7 @@ Your default hypothesis is that the code is broken despite passing automated che If during Step 2 or Step 4 you discover behavior not covered by existing acceptance criteria: - Do not extend criteria yourself — escalate to the PO -- Note the gap in `WORK.md` `Next:` line and Session Log +- Note the gap in `WORK.md` and escalate to PO ## Available Skills diff --git a/.opencode/skills/architect/.system.md.template.swp b/.opencode/skills/architect/.system.md.template.swp new file mode 100644 index 0000000..66c0379 Binary files /dev/null and b/.opencode/skills/architect/.system.md.template.swp differ diff --git a/.opencode/skills/architect/SKILL.md b/.opencode/skills/architect/SKILL.md index 55f005b..f7c1436 100644 --- a/.opencode/skills/architect/SKILL.md +++ b/.opencode/skills/architect/SKILL.md @@ -31,7 +31,7 @@ Design correctness is far more important than lint/pyright/coverage compliance. ### Prerequisites (stop if any fail — escalate to PO) -1. `docs/features/in-progress/` contains exactly one `.feature` file (not just `.gitkeep`). If none exists, **STOP** — update FLOW.md `Next:` to `Run @product-owner — move the chosen feature to in-progress/` and stop. Never self-select or move a feature yourself. +1. `docs/features/in-progress/` contains exactly one `.feature` file (not just `.gitkeep`). If none exists, **STOP** — update `WORK.md` `@state` to `[IDLE]` and stop. Never self-select or move a feature yourself. 2. The feature file's discovery section has `Status: BASELINED`. If not, escalate to PO — Step 1 is incomplete. 3. The feature file contains `Rule:` blocks with `Example:` blocks and `@id` tags. If not, escalate to PO — criteria have not been written. 4. Package name confirmed: read `pyproject.toml` → locate `[tool.setuptools]` → confirm directory exists on disk. @@ -116,8 +116,8 @@ Only create an ADR for non-obvious decisions with meaningful trade-offs. Routine ## Domain Analysis From `docs/glossary.md` + Rules (Business) in the `.feature` file: -- **Nouns** → candidate classes, value objects, aggregates -- **Verbs** → method names with typed signatures +- **Nouns** in feature/glossary language → candidate Entities, Value Objects, or Aggregates in the domain model +- **Verbs** in feature/glossary language → candidate Actions (operations with typed signatures on an Entity, a standalone function, or a Domain Service) - **Datasets** → named types (not bare dict/list) - **Bounded Context check**: same word, different meaning across features? → module boundary - **Cross-feature entities** → candidate shared domain layer @@ -126,8 +126,8 @@ From `docs/glossary.md` + Rules (Business) in the `.feature` file: Update the `## Domain Model` section of `docs/system.md`: -- **New feature, first entities**: add bounded contexts, entities, verbs, and relationships to the Domain Model section. -- **Existing feature**: append new entities and verbs. Deprecate old entries if superseded — move them to a `### Deprecated` subsection. Never edit existing live entries — code depends on them. +- **New feature, first entities**: add bounded contexts, entities, actions, and relationships to the Domain Model section. +- **Existing feature**: append new entities and actions. Deprecate old entries if superseded — move them to a `### Deprecated` subsection. Never edit existing live entries — code depends on them. - Update the `## Context` and `## Container` sections if new actors, external systems, or containers are identified. The PO reads `docs/system.md` but never writes to it. @@ -196,7 +196,7 @@ Commit: `feat(): add architecture and test stubs` ### Hand off to Step 3 (TDD Loop) -1. Update FLOW.md: `Next: Run @software-engineer — Step 3 TDD Loop` +1. Update `WORK.md` `@state: STEP-3-WORKING` 2. Provide the SE with: - Feature file path - Summary of stubs created @@ -210,7 +210,7 @@ Commit: `feat(): add architecture and test stubs` If during architecture you discover behavior not covered by existing acceptance criteria: - **Do not extend criteria yourself** — escalate to PO -- Note the gap in `WORK.md` Next: line and Session Log +- Note the gap in `WORK.md` and escalate to PO - The PO will decide whether to add a new Example to the `.feature` file --- @@ -222,6 +222,6 @@ Templates for files written by this skill live in this skill's directory (`archi - `system.md.template` — `docs/system.md` structure (domain model + Context + Container sections included) - `adr.md.template` — individual ADR file structure (includes `## Context` section) -Base directory for this skill: file:///home/user/Documents/projects/python-project-template/.opencode/skills/architect +Base directory for this skill: `.opencode/skills/architect/` Relative paths in this skill (e.g., scripts/, reference/) are relative to this base directory. Note: file list is sampled. diff --git a/.opencode/skills/implement/system.md.template b/.opencode/skills/architect/system.md.template similarity index 84% rename from .opencode/skills/implement/system.md.template rename to .opencode/skills/architect/system.md.template index a492697..be57a74 100644 --- a/.opencode/skills/implement/system.md.template +++ b/.opencode/skills/architect/system.md.template @@ -13,47 +13,57 @@ --- -## Actors +## Context -| Actor | Needs | -|-------|-------| -| `` | | +```mermaid +%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '', 'lineColor': ''}}}%% +C4Context + title System Context — ---- + Person(, "", "") -## Structure + System(, "", "") -| Module | Responsibility | -|--------|----------------| -| `` | | + System_Ext(, "", "") + + Rel(, , "