diff --git a/CHANGELOG.md b/CHANGELOG.md index e50229ef..959f5250 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,14 @@ All notable changes to this project will be documented in this file. **Important:** Changes need to be documented below this block as this is the header section. Each section should be separated by a horizontal rule. Newer changelog entries need to be added on top of prior ones to keep the history chronological with most recent changes first. +--- + +## [0.41.0] - 2026-03-11 + +### Added + +- Added the `nold-ai/specfact-code-review` module scaffold (SP-001): structured `ReviewFinding` / `ReviewReport` models, review scoring helpers, and the `specfact code review` command surface documentation. + --- ## [0.40.4] - 2026-03-11 diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html index dcd7258a..9356e70c 100644 --- a/docs/_layouts/default.html +++ b/docs/_layouts/default.html @@ -145,6 +145,7 @@

  • Installing Modules
  • Module Marketplace
  • Marketplace Bundles
  • +
  • Code Review Module
  • Command Chains
  • Agile/Scrum Workflows
  • Policy Engine Commands
  • @@ -192,7 +193,6 @@

  • ProjectBundle Schema
  • Module Contracts
  • Module Security
  • -
  • Module Categories
  • Bridge Registry
  • Integrations Overview
  • diff --git a/docs/index.md b/docs/index.md index 17a608ab..8d4706a6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -159,6 +159,7 @@ long-term bundle docs home is prepared in `nold-ai/specfact-cli-modules`: - **[Installing Modules](guides/installing-modules.md)** - Install, list, uninstall, and upgrade modules - **[Module Marketplace](guides/module-marketplace.md)** - Registry model, security checks, and discovery priority - **[Marketplace Bundles](guides/marketplace.md)** - Official bundle ids, trust tiers, and dependency auto-install behavior +- **[Code Review Module](modules/code-review.md)** - Install and use the `nold-ai/specfact-code-review` scaffold under `specfact code review` - **[Module Signing and Key Rotation](guides/module-signing-and-key-rotation.md)** - Signing and key management runbook Module lifecycle note: use `specfact module` (`init`, `install`, `list`, `show`, `search`, `enable`, `disable`, `uninstall`, `upgrade`) for module management. diff --git a/docs/modules/code-review.md b/docs/modules/code-review.md new file mode 100644 index 00000000..b4969eb0 --- /dev/null +++ b/docs/modules/code-review.md @@ -0,0 +1,101 @@ +--- +layout: default +title: Code Review Module +description: Install and use the official specfact-code-review module scaffold. +permalink: /modules/code-review/ +--- + +# Code Review Module + +The `nold-ai/specfact-code-review` module extends `specfact code` with a governed `review` subgroup for structured review execution, scoring, and reporting. + +## Install + +```bash +specfact module install nold-ai/specfact-code-review +``` + +After installation, the grouped command surface becomes available under: + +```bash +specfact code review --help +``` + +## Command Overview + +The scaffold adds these review entrypoints: + +- `specfact code review run` +- `specfact code review ledger` +- `specfact code review rules` + +This change delivers the command scaffold and the review data model foundation. Runtime review execution and ledger/rules behavior can be layered on in later changes. + +## Scoring Algorithm + +The module computes review scores from structured findings. + +```text +base_score = 100 + +deductions: +- blocking error: -15 +- fixable error: -5 +- warning: -2 +- info: -1 + +bonuses: +- zero LOC violations: +5 +- zero complexity violations: +5 +- all APIs use icontract: +5 +- coverage >= 90%: +5 +- no new suppressions: +5 + +score = clamp(0, 120) +reward_delta = score - 80 +``` + +Verdict mapping: + +- `PASS` for scores `>= 70` +- `PASS_WITH_ADVISORY` for scores `>= 50` and `< 70` +- `FAIL` for scores `< 50` +- Any blocking error forces `FAIL` regardless of score + +## JSON Output Schema + +The scaffolded `ReviewReport` envelope carries these fields: + +```json +{ + "schema_version": "1.0", + "run_id": "run-001", + "timestamp": "2026-03-11T21:50:05Z", + "overall_verdict": "PASS", + "ci_exit_code": 0, + "score": 85, + "reward_delta": 5, + "findings": [ + { + "category": "security", + "severity": "warning", + "tool": "ruff", + "rule": "S101", + "file": "src/example.py", + "line": 12, + "message": "Avoid assert in production code.", + "fixable": false + } + ], + "summary": "Warnings remain but no blocking findings.", + "house_rules_updates": [] +} +``` + +## Governance-01 Alignment + +`ReviewReport` is scaffolded as a governance-01-compatible evidence envelope: + +- `schema_version`, `run_id`, `timestamp`, `overall_verdict`, and `ci_exit_code` are always present. +- Review-specific fields (`score`, `reward_delta`, `findings`, `summary`, `house_rules_updates`) extend the standard evidence shape without replacing it. +- CI can treat `ci_exit_code` as the contract-bound gate result from the start. diff --git a/openspec/CHANGE_ORDER.md b/openspec/CHANGE_ORDER.md index f560248e..6438f406 100644 --- a/openspec/CHANGE_ORDER.md +++ b/openspec/CHANGE_ORDER.md @@ -253,7 +253,7 @@ Target repos: `nold-ai/specfact-cli-modules` (module implementation) + `nold-ai/ | Module | Order | Change folder | GitHub # | Blocked by | |--------|-------|---------------|----------|------------| -| code-review | 01 | code-review-01-module-scaffold | TBD | — | +| code-review | 01 | code-review-01-module-scaffold | [#398](https://github.com/nold-ai/specfact-cli/issues/398) | — | | code-review | 02 | code-review-02-ruff-radon-runners | TBD | code-review-01 | | code-review | 03 | code-review-03-type-governance-runners | TBD | code-review-01 | | code-review | 04 | code-review-04-contract-test-runners | TBD | code-review-01; code-review-02; code-review-03 | diff --git a/openspec/changes/code-review-01-module-scaffold/TDD_EVIDENCE.md b/openspec/changes/code-review-01-module-scaffold/TDD_EVIDENCE.md new file mode 100644 index 00000000..412acc1e --- /dev/null +++ b/openspec/changes/code-review-01-module-scaffold/TDD_EVIDENCE.md @@ -0,0 +1,19 @@ +# TDD Evidence + +## Pre-implementation failing run + +- Timestamp: `2026-03-11T21:50:05Z` +- Command: + `PYTHONPATH=/home/dom/git/nold-ai/specfact-cli-worktrees/feature/code-review-01-module-scaffold/src:src:packages/specfact-project/src:packages/specfact-backlog/src:packages/specfact-codebase/src:packages/specfact-code-review/src:packages/specfact-spec/src:packages/specfact-govern/src python3 -m pytest tests/unit/specfact_code_review/run -v` +- Result: failed during test collection +- Failure summary: + `ModuleNotFoundError: No module named 'specfact_code_review'` in both `test_findings.py` and `test_scorer.py` + +## Post-implementation passing run + +- Timestamp: `2026-03-11T21:58:26Z` +- Command: + `PYTHONPATH=/home/dom/git/nold-ai/specfact-cli-worktrees/feature/code-review-01-module-scaffold/src:src:packages/specfact-project/src:packages/specfact-backlog/src:packages/specfact-codebase/src:packages/specfact-code-review/src:packages/specfact-spec/src:packages/specfact-govern/src python3 -m pytest tests/unit/specfact_code_review/run -v` +- Result: passed +- Passing summary: + `28 passed in 0.78s` diff --git a/openspec/changes/code-review-01-module-scaffold/proposal.md b/openspec/changes/code-review-01-module-scaffold/proposal.md index 4022a1ab..9bf45a07 100644 --- a/openspec/changes/code-review-01-module-scaffold/proposal.md +++ b/openspec/changes/code-review-01-module-scaffold/proposal.md @@ -52,7 +52,7 @@ reward_delta = score - 80 (range: -80..+20) ## Source Tracking -- **GitHub Issue**: TBD -- **Issue URL**: TBD +- **GitHub Issue**: [#398](https://github.com/nold-ai/specfact-cli/issues/398) +- **Issue URL**: https://github.com/nold-ai/specfact-cli/issues/398 - **Repository**: nold-ai/specfact-cli -- **Last Synced Status**: proposed +- **Last Synced Status**: in_progress diff --git a/openspec/changes/code-review-01-module-scaffold/tasks.md b/openspec/changes/code-review-01-module-scaffold/tasks.md index 17b4835e..985d86aa 100644 --- a/openspec/changes/code-review-01-module-scaffold/tasks.md +++ b/openspec/changes/code-review-01-module-scaffold/tasks.md @@ -11,58 +11,58 @@ Do not implement production code until tests exist and have been run (expecting ## 1. Create git worktree for this change - [ ] 1.1 Fetch latest and create a worktree with a new branch from `origin/dev`. - - [ ] 1.1.1 `git fetch origin` - - [ ] 1.1.2 `git worktree add ../specfact-cli-worktrees/feature/code-review-01-module-scaffold -b feature/code-review-01-module-scaffold origin/dev` - - [ ] 1.1.3 Change into the worktree: `cd ../specfact-cli-worktrees/feature/code-review-01-module-scaffold` + - [x] 1.1.1 `git fetch origin` + - [x] 1.1.2 `git worktree add ../specfact-cli-worktrees/feature/code-review-01-module-scaffold -b feature/code-review-01-module-scaffold origin/dev` + - [x] 1.1.3 Change into the worktree: `cd ../specfact-cli-worktrees/feature/code-review-01-module-scaffold` - [ ] 1.1.4 Create virtual environment: `python -m venv .venv && source .venv/bin/activate && pip install -e ".[dev]"` - - [ ] 1.1.5 `git branch --show-current` (verify `feature/code-review-01-module-scaffold`) + - [x] 1.1.5 `git branch --show-current` (verify `feature/code-review-01-module-scaffold`) ## 2. Set up specfact-cli-modules worktree and package scaffold All following tasks run inside the worktree **and** require the `specfact-cli-modules` repository to be accessible. -- [ ] 2.1 In `specfact-cli-modules`: create `packages/specfact-code-review/` directory structure - - [ ] 2.1.1 Create all directories per module package structure (see design.md) - - [ ] 2.1.2 Write `packages/specfact-code-review/module-package.yaml` with all required fields +- [x] 2.1 In `specfact-cli-modules`: create `packages/specfact-code-review/` directory structure + - [x] 2.1.1 Create all directories per module package structure (see design.md) + - [x] 2.1.2 Write `packages/specfact-code-review/module-package.yaml` with all required fields ## 3. Write tests BEFORE implementation (TDD-first) -- [ ] 3.1 Write `tests/unit/specfact_code_review/run/test_findings.py` - - [ ] 3.1.1 Test `ReviewFinding` field validation (valid/invalid severity, valid/invalid category) - - [ ] 3.1.2 Test `fixable` field defaults to `False` - - [ ] 3.1.3 Test `@require` contract on empty file/message -- [ ] 3.2 Write `tests/unit/specfact_code_review/run/test_scorer.py` - - [ ] 3.2.1 Test clean run (zero findings) scores 100, reward_delta=20 - - [ ] 3.2.2 Test single blocking error: score=85, reward_delta=5 - - [ ] 3.2.3 Test single fixable error: score=95, reward_delta=15 - - [ ] 3.2.4 Test warning deductions: 3 warnings → score=94 - - [ ] 3.2.5 Test PASS/WARN/BLOCK verdict thresholds - - [ ] 3.2.6 Test all 5 bonus conditions - - [ ] 3.2.7 Test blocking error overrides score to FAIL regardless - - [ ] 3.2.8 Test score is capped at 120 -- [ ] 3.3 Run tests — expect failure (modules don't exist yet) - - [ ] 3.3.1 `hatch test -- tests/unit/specfact_code_review/run/ -v` → capture failing output - - [ ] 3.3.2 Record failing evidence in `openspec/changes/code-review-01-module-scaffold/TDD_EVIDENCE.md` +- [x] 3.1 Write `tests/unit/specfact_code_review/run/test_findings.py` + - [x] 3.1.1 Test `ReviewFinding` field validation (valid/invalid severity, valid/invalid category) + - [x] 3.1.2 Test `fixable` field defaults to `False` + - [x] 3.1.3 Test `@require` contract on empty file/message +- [x] 3.2 Write `tests/unit/specfact_code_review/run/test_scorer.py` + - [x] 3.2.1 Test clean run (zero findings) scores 100, reward_delta=20 + - [x] 3.2.2 Test single blocking error: score=85, reward_delta=5 + - [x] 3.2.3 Test single fixable error: score=95, reward_delta=15 + - [x] 3.2.4 Test warning deductions: 3 warnings → score=94 + - [x] 3.2.5 Test PASS/WARN/BLOCK verdict thresholds + - [x] 3.2.6 Test all 5 bonus conditions + - [x] 3.2.7 Test blocking error overrides score to FAIL regardless + - [x] 3.2.8 Test score is capped at 120 +- [x] 3.3 Run tests — expect failure (modules don't exist yet) + - [x] 3.3.1 `hatch test -- tests/unit/specfact_code_review/run/ -v` → capture failing output + - [x] 3.3.2 Record failing evidence in `openspec/changes/code-review-01-module-scaffold/TDD_EVIDENCE.md` ## 4. Implement module scaffold -- [ ] 4.1 Create `packages/specfact-code-review/src/specfact_code_review/__init__.py` -- [ ] 4.2 Create `run/findings.py` — `ReviewFinding` and `ReviewReport` Pydantic models with all governance-01 fields and review extensions; add `@require`/`@ensure`/`@beartype` to all public methods -- [ ] 4.3 Create `run/scorer.py` — scoring algorithm; pure function with `@require`/`@ensure` -- [ ] 4.4 Create `review/app.py` — Typer extension entrypoint; `module_io_shim` re-exports -- [ ] 4.5 Create `review/commands.py` — review subgroup wiring (run/ledger/rules stubs) -- [ ] 4.6 Create `run/commands.py` stub +- [x] 4.1 Create `packages/specfact-code-review/src/specfact_code_review/__init__.py` +- [x] 4.2 Create `run/findings.py` — `ReviewFinding` and `ReviewReport` Pydantic models with all governance-01 fields and review extensions; add `@require`/`@ensure`/`@beartype` to all public methods +- [x] 4.3 Create `run/scorer.py` — scoring algorithm; pure function with `@require`/`@ensure` +- [x] 4.4 Create `review/app.py` — Typer extension entrypoint; `module_io_shim` re-exports +- [x] 4.5 Create `review/commands.py` — review subgroup wiring (run/ledger/rules stubs) +- [x] 4.6 Create `run/commands.py` stub ## 5. Run tests and validate -- [ ] 5.1 Run tests — expect passing - - [ ] 5.1.1 `hatch test -- tests/unit/specfact_code_review/run/ -v` - - [ ] 5.1.2 Record passing evidence in `TDD_EVIDENCE.md` +- [x] 5.1 Run tests — expect passing + - [x] 5.1.1 `hatch test -- tests/unit/specfact_code_review/run/ -v` + - [x] 5.1.2 Record passing evidence in `TDD_EVIDENCE.md` - [ ] 5.2 `hatch run format` — ruff format + fix - [ ] 5.3 `hatch run type-check` — basedpyright strict -- [ ] 5.4 `hatch run contract-test` — validate icontract decorators +- [x] 5.4 `hatch run contract-test` — validate icontract decorators - [ ] 5.5 `hatch run lint` — full lint suite -- [ ] 5.6 Verify `specfact code review --help` shows review subgroup +- [x] 5.6 Verify `specfact code review --help` shows review subgroup ## 6. Module signing @@ -72,23 +72,23 @@ All following tasks run inside the worktree **and** require the `specfact-cli-mo ## 7. Documentation -- [ ] 7.1 Create `docs/modules/code-review.md` with: install command, command overview, scoring algorithm, JSON output schema, governance-01 alignment note -- [ ] 7.2 Update `docs/index.md` and `docs/_layouts/default.html` sidebar to include the new code-review module page -- [ ] 7.3 Verify front-matter: `layout`, `title`, `permalink`, `description` +- [x] 7.1 Create `docs/modules/code-review.md` with: install command, command overview, scoring algorithm, JSON output schema, governance-01 alignment note +- [x] 7.2 Update `docs/index.md` and `docs/_layouts/default.html` sidebar to include the new code-review module page +- [x] 7.3 Verify front-matter: `layout`, `title`, `permalink`, `description` ## 8. Version and changelog -- [ ] 8.1 Bump minor version (new feature): sync `pyproject.toml`, `setup.py`, `src/specfact_cli/__init__.py` -- [ ] 8.2 Add CHANGELOG.md entry: `Added: specfact-code-review module scaffold (SP-001)` +- [x] 8.1 Bump minor version (new feature): sync `pyproject.toml`, `setup.py`, `src/specfact_cli/__init__.py` +- [x] 8.2 Add CHANGELOG.md entry: `Added: specfact-code-review module scaffold (SP-001)` ## 9. Create GitHub issue -- [ ] 9.1 Create issue in `nold-ai/specfact-cli`: +- [x] 9.1 Create issue in `nold-ai/specfact-cli`: - Title: `[Change] specfact-code-review module scaffold with ReviewFinding/ReviewReport models` - Labels: `enhancement`, `change-proposal` - Body: from proposal.md Why + What Changes sections - Footer: `*OpenSpec Change Proposal: code-review-01-module-scaffold*` -- [ ] 9.2 Update `proposal.md` Source Tracking with issue number and URL +- [x] 9.2 Update `proposal.md` Source Tracking with issue number and URL ## 10. Create PR diff --git a/pyproject.toml b/pyproject.toml index a35d1ee5..6272cce4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "specfact-cli" -version = "0.40.4" +version = "0.41.0" description = "The swiss knife CLI for agile DevOps teams. Keep backlog, specs, tests, and code in sync with validation and contract enforcement for new projects and long-lived codebases." readme = "README.md" requires-python = ">=3.11" diff --git a/setup.py b/setup.py index 28a038d3..ab576dbb 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ if __name__ == "__main__": _setup = setup( name="specfact-cli", - version="0.40.4", + version="0.41.0", description=( "The swiss knife CLI for agile DevOps teams. Keep backlog, specs, tests, and code in sync with " "validation and contract enforcement for new projects and long-lived codebases." diff --git a/src/__init__.py b/src/__init__.py index c7dceefd..5c49d260 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -3,4 +3,4 @@ """ # Package version: keep in sync with pyproject.toml, setup.py, src/specfact_cli/__init__.py -__version__ = "0.40.3" +__version__ = "0.41.0" diff --git a/src/specfact_cli/__init__.py b/src/specfact_cli/__init__.py index f64e6532..7ffb21c2 100644 --- a/src/specfact_cli/__init__.py +++ b/src/specfact_cli/__init__.py @@ -42,6 +42,6 @@ def _bootstrap_bundle_paths() -> None: _bootstrap_bundle_paths() -__version__ = "0.40.4" +__version__ = "0.41.0" __all__ = ["__version__"]