Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
dbb3061
feat(discovery): complete session 1 — CLI entrypoint chosen as demons…
nullhack Apr 22, 2026
1807b3d
feat(criteria): write acceptance criteria for cli-entrypoint
nullhack Apr 22, 2026
4f60188
chore: move cli-entrypoint to in-progress, ready for Step 2
nullhack Apr 22, 2026
42addfd
fix(workflow): remove Session Log and Next: from WORK.md and all skil…
nullhack Apr 22, 2026
7df5886
fix(workflow): replace Verbs/Nouns with Actions/Entities in SA-owned …
nullhack Apr 22, 2026
f724cab
feat(cli-entrypoint): add architecture stubs and ADRs
nullhack Apr 22, 2026
b0394d0
feat(cli-entrypoint): generate test stubs
nullhack Apr 22, 2026
97b961e
chore: cli-entrypoint transition to STEP-3-WORKING
nullhack Apr 22, 2026
c06c281
fix(cli-entrypoint): convert module dependency graph to mermaid for c…
nullhack Apr 22, 2026
bb8b061
fix(cli-entrypoint): reorder system.md sections — zoom-in narrative f…
nullhack Apr 22, 2026
ab1f2d5
feat(cli-entrypoint): implement --help and --version CLI entrypoint
nullhack Apr 22, 2026
75e7685
chore: cli-entrypoint transition to STEP-4-READY
nullhack Apr 22, 2026
c1251c7
chore: cli-entrypoint transition to STEP-5-READY
nullhack Apr 22, 2026
26873e1
feat(cli-entrypoint): Step 5 acceptance — move to completed, update s…
nullhack Apr 22, 2026
768675b
feat(cli-entrypoint): merge to main — CLI entrypoint accepted
nullhack Apr 22, 2026
dfa5b42
design(assets): replace explicit 8 glyph with structural crossbeam li…
nullhack Apr 22, 2026
7cd3be1
design(assets): refine temple mark — inner-wall shadows, stair gradin…
nullhack Apr 22, 2026
3fe70ec
docs(update-docs): apply branding colors to C4 diagrams and fix proje…
nullhack Apr 22, 2026
8304a2c
docs(index): redesign portal with branding palette, inline features/A…
nullhack Apr 22, 2026
89b78a7
docs(index): add system/discovery/glossary cards, link features and r…
nullhack Apr 22, 2026
ad68d28
chore(release): bump version to v7.2.20260422 - Resolute Hermes
nullhack Apr 22, 2026
49b2010
fix(ci): scope pyright to app/tests, install package before tests in CI
nullhack Apr 22, 2026
21c7cec
fix(scripts): correct pyright type errors in check_oc and detect_state
nullhack Apr 22, 2026
7e7b868
fix(ci): revert editable install step, use venv-scoped uv sync for tests
nullhack Apr 22, 2026
c3c7ef1
fix(ci): scope UV_SYSTEM_PYTHON override to test job so uv installs p…
nullhack Apr 22, 2026
0849f0e
fix(ci): add uv pip install -e . to create dist-info for importlib.me…
nullhack Apr 22, 2026
09646b9
fix(ci): set UV_SYSTEM_PYTHON=false (not empty string) at test job level
nullhack Apr 22, 2026
1409762
fix(ci): apply UV_SYSTEM_PYTHON=false and editable install to build j…
nullhack Apr 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ jobs:
fail-fast: false
matrix:
python-version: ["3.13"]
env:
UV_SYSTEM_PYTHON: "false"

steps:
- name: Checkout code
Expand All @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
19 changes: 19 additions & 0 deletions .github/workflows/tag-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
6 changes: 3 additions & 3 deletions .opencode/agents/product-owner.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/<name>.feature` → `docs/features/completed/<name>.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/<name>.feature` → `docs/features/completed/<name>.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

Expand All @@ -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 <feature-stem>`.
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
Expand Down
4 changes: 2 additions & 2 deletions .opencode/agents/software-engineer.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
6 changes: 3 additions & 3 deletions .opencode/agents/system-architect.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/<stem>`
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
Expand All @@ -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

Expand Down
Binary file not shown.
16 changes: 8 additions & 8 deletions .opencode/skills/architect/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -196,7 +196,7 @@ Commit: `feat(<feature-stem>): 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
Expand All @@ -210,7 +210,7 @@ Commit: `feat(<feature-stem>): 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

---
Expand All @@ -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.
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,57 @@

---

## Actors
## Context

| Actor | Needs |
|-------|-------|
| `<role>` | <description> |
```mermaid
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '<branding.Visual.Stone/marble hex>', 'lineColor': '<branding.Visual.Accent/gold hex>'}}}%%
C4Context
title System Context — <project-name>

---
Person(<id>, "<Name>", "<description>")

## Structure
System(<id>, "<Name>", "<description>")

| Module | Responsibility |
|--------|----------------|
| `<module>` | <responsibility> |
System_Ext(<id>, "<Name>", "<description>")

Rel(<from>, <to>, "<label>", "<technology>")
```

---

## Key Decisions
## Actors

- <system-wide decision from ADRs — one bullet per decision>
| Actor | Needs |
|-------|-------|
| `<role>` | <description> |

---

## Configuration Keys
## Container

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `<key>` | string | `"<default>"` | <description> |
```mermaid
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '<branding.Visual.Stone/marble hex>', 'lineColor': '<branding.Visual.Accent/gold hex>'}}}%%
C4Container
title Container Diagram — <project-name>

---
Person(<id>, "<Name>", "")

## External Dependencies
System_Boundary(<id>, "<Name>") {
Container(<id>, "<Name>", "<technology>", "<description>")
}

| Dependency | What it provides | Why not replaced |
|------------|------------------|-----------------|
| `<dep>` | <purpose> | <reason> |
System_Ext(<id>, "<Name>", "<description>")

Rel(<from>, <to>, "<label>")
```

---

## Active Constraints
## Structure

- <system-wide constraint from ADRs or completed features>
| Module | Responsibility |
|--------|----------------|
| `<module>` | <responsibility> |

---

Expand All @@ -72,11 +82,11 @@
| `<Name>` | Entity | <description> | <Context> |
| `<Name>` | Value Object | <description> | <Context> |

### Verbs
### Actions

| Name | Actor | Object | Description |
|------|-------|--------|-------------|
| `<verb>` | <who> | <what> → <result> | <description> |
| `<action>` | <who> | <what> → <result> | <description> |

### Relationships

Expand All @@ -86,45 +96,41 @@

### Module Dependency Graph

```
<module> ──► <module> ──► (<external>)
```mermaid
graph LR
<module>["<module>"]
<dep>["<dep> (stdlib|external)"]

<module> --> <dep>
```

---

## Context

```mermaid
C4Context
title System Context — <project-name>
## Active Constraints

Person(<id>, "<Name>", "<description>")
- <system-wide constraint from ADRs or completed features>

System(<id>, "<Name>", "<description>")
---

System_Ext(<id>, "<Name>", "<description>")
## Key Decisions

Rel(<from>, <to>, "<label>", "<technology>")
```
- <system-wide decision from ADRs — one bullet per decision>

---

## Container

```mermaid
C4Container
title Container Diagram — <project-name>
## Configuration Keys

Person(<id>, "<Name>", "")
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `<key>` | string | `"<default>"` | <description> |

System_Boundary(<id>, "<Name>") {
Container(<id>, "<Name>", "<technology>", "<description>")
}
---

System_Ext(<id>, "<Name>", "<description>")
## External Dependencies

Rel(<from>, <to>, "<label>")
```
| Dependency | What it provides | Why not replaced |
|------------|------------------|-----------------|
| `<dep>` | <purpose> | <reason> |

---

Expand Down
4 changes: 2 additions & 2 deletions .opencode/skills/check-quality/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Load this skill when completing Step 3 and preparing to hand off to the system-a
```bash
uv run task lint # ruff check + ruff format — must exit 0
uv run task static-check # pyright — must exit 0, 0 errors
uv run task test # pytest with coverage — must exit 0, 100% coverage
uv run task test-coverage # pytest with coverage — must exit 0, coverage passes
timeout 10s uv run task run # app starts — must exit non-124
```

Expand All @@ -32,6 +32,6 @@ All four must pass. Do not hand off broken work.

- [ ] `lint` exits 0 (ruff check + ruff format)
- [ ] `static-check` exits 0, 0 pyright errors
- [ ] `test` exits 0, 100% coverage
- [ ] `test-coverage` exits 0, coverage passes
- [ ] `run` exits non-124 (not hung)
- [ ] No `noqa` or `type: ignore` — fix the underlying issue
2 changes: 1 addition & 1 deletion .opencode/skills/create-pr/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ EOF
- [ ] All commits follow conventional commit format
- [ ] `task lint` exits 0
- [ ] `task static-check` exits 0
- [ ] `task test` exits 0, coverage 100%
- [ ] `task test` exits 0, coverage passes
- [ ] `timeout 10s task run` exits with code ≠ 124
- [ ] PR description includes all `@id` acceptance criteria

Expand Down
11 changes: 6 additions & 5 deletions .opencode/skills/define-scope/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ Stakeholder reports a feature is wrong after PO acceptance attempt.
```
4. **PO scans `docs/post-mortem/`**, selects relevant files by `<feature-stem>` or `<failure-keyword>` in filename.
5. **PO reads selected post-mortems** for context before handoff.
6. **PO updates `WORK.md`**: set `@state: STEP-2-ARCH`, `@branch: fix/<feature-stem>`; append to Session Log; set `Next: Run @system-architect — restart Step 2 for <feature-stem> on fix/<feature-stem> with post-mortem context`.
6. **PO updates `WORK.md`**: set `@state: STEP-2-ARCH`, `@branch: fix/<feature-stem>`.
7. **SA begins Step 2** on `fix/<feature-stem>`, reading relevant post-mortems as input.

### Document Format
Expand All @@ -452,13 +452,14 @@ All templates for files written by this skill live in this skill's directory:
- `discovery.md.template` — `docs/discovery.md` per-session block
- `feature.md.template` — `.feature` file structure
- `post-mortem.md.template` — `docs/post-mortem/YYYY-MM-DD-<feature-stem>-<keyword>.md` structure
- `glossary.md.template` — `docs/glossary.md` initial file (pre-filled with common jargon; PO appends project-specific entries)

Base directory for this skill: file:///home/user/Documents/projects/python-project-template/.opencode/skills/define-scope
Base directory for this skill: `.opencode/skills/define-scope/`
Relative paths in this skill (e.g., scripts/, reference/) are relative to this base directory.
Note: file list is sampled.

<skill_files>
<file>/home/user/Documents/projects/python-project-template/.opencode/skills/define-scope/discovery.md.template</file>
<file>/home/user/Documents/projects/python-project-template/.opencode/skills/define-scope/feature.md.template</file>
<file>/home/user/Documents/projects/python-project-template/.opencode/skills/define-scope/scope-journal.md.template</file>
<file>.opencode/skills/define-scope/discovery.md.template</file>
<file>.opencode/skills/define-scope/feature.md.template</file>
<file>.opencode/skills/define-scope/scope-journal.md.template</file>
</skill_files>
Loading
Loading