Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
40 changes: 10 additions & 30 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,30 @@ default_stages:
- pre-commit
- pre-push

# Configuration for pre-commit hooks
repos:
# General hooks from the pre-commit-hooks repository
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
rev: v6.0.0
hooks:
- id: trailing-whitespace
# Removes any trailing whitespace from lines in text files
- id: end-of-file-fixer
# Ensures files end with a newline
- id: check-yaml
exclude: '^helm-chart/templates.*\.yaml$|^mkdocs\.yml$'
# Checks YAML files for syntax errors
- id: check-json
# Checks JSON files for syntax errors
- id: check-ast
name: "Check Python syntax (AST validation)"
# Validates that Python files have valid syntax
- id: check-added-large-files

# Ruff hooks for Python linting and formatting
# Ruff: The One Tool to Rule Them All
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.9
rev: v0.3.0
hooks:
# First, run ruff format - won't change imports but will format them
- id: ruff-format
name: "Format code (without changing imports)"

# Then, use a single ruff pass for both import sorting and linting
# Linter (Fixes imports, modernizes syntax, checks bugs)
- id: ruff
name: "Linting and import sorting"
args: ["--fix"]

# Pyupgrade: Check and fix Python version incompatibilities and outdated syntax
- repo: https://github.com/asottile/pyupgrade
rev: v3.15.2
hooks:
- id: pyupgrade
name: "Upgrade syntax for Python 3.12+"
args: [--py312-plus]
# Auto-fixes outdated syntax to Python 3.12+ compatible code
args: [--fix, --exit-non-zero-on-fix]
# Formatter (Replaces Black)
- id: ruff-format

# Conventional pre-commit hooks for commit messages
# Convention Enforcement
- repo: https://github.com/compilerla/conventional-pre-commit
rev: v4.0.0
rev: v4.3.0
hooks:
- id: conventional-pre-commit
stages: [commit-msg]
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,3 +235,11 @@ This format allows for intelligent, context-aware rule evaluation while maintain
## Contributing & Development

For instructions on running tests, local development, and contributing, see [DEVELOPMENT.md](DEVELOPMENT.md).

## Unauthenticated Analysis & Rate Limiting

- The repository analysis endpoint `/v1/rules/recommend` now supports unauthenticated access for public GitHub repositories.
- Anonymous users are limited to 5 requests per hour per IP. Authenticated users are limited to 100 requests per hour.
- Exceeding the limit returns a 429 error with a `Retry-After` header.
- For private repositories, authentication is required.
- The frontend is now fully connected to the backend and no longer uses mock data.
Comment on lines +238 to +245
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for the recommend endpoint definition in the API code
rg -n "rules/recommend|/recommend" --type=py -C3

Repository: warestack/watchflow

Length of output: 3906


🏁 Script executed:

#!/bin/bash
# Find where the recommendations router is mounted
rg -n "include_router|recommendations|APIRouter" --type=py src/api/ -B2 -A2 | head -50

Repository: warestack/watchflow

Length of output: 2253


🏁 Script executed:

#!/bin/bash
# Find the main app configuration
fd -n "main.py|app.py" -t f | head -5
# Then search for include_router calls
rg -n "include_router" --type=py

Repository: warestack/watchflow

Length of output: 719


Update the endpoint path in the documentation to match the actual API.

The endpoint in the README should be /api/v1/rules/recommend, not /v1/rules/recommend. The full path includes the /api prefix, as confirmed by the router mounting in src/main.py (line 103) and the integration tests.

The rest of the documentation is clear and accurate—rate limits, authentication requirements, and the 429 response handling are all correctly described.

🤖 Prompt for AI Agents
In `@README.md` around lines 238 - 245, The README incorrectly lists the
repository analysis endpoint as /v1/rules/recommend; update the documentation to
use the actual mounted path /api/v1/rules/recommend. Edit the README.md entry
under "Unauthenticated Analysis & Rate Limiting" to replace
`/v1/rules/recommend` with `/api/v1/rules/recommend` (consistent with the API
router mount via app.include_router and the integration tests), and verify any
other README references to the endpoint include the /api prefix.

9 changes: 9 additions & 0 deletions docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,3 +276,12 @@ standards so teams can focus on building, increase trust, and move fast.
- Error rate monitoring
- Capacity planning insights
- Predictive maintenance

---

## Unauthenticated Analysis & Rate Limiting

- The repository analysis endpoint allows public repo analysis without authentication (5 requests/hour/IP for anonymous users).
- Authenticated users can analyze up to 100 repos/hour.
- Exceeding limits returns a 429 error with a Retry-After header.
- Private repo analysis requires authentication.
9 changes: 9 additions & 0 deletions linting_commands.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Run all pre-commit hooks on all files
pre-commit run --all-files

# Run ruff linter and formatter directly (if needed)
ruff check src/
ruff format src/

# Run mypy for type checking
mypy src/
221 changes: 41 additions & 180 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,91 +1,3 @@
[tool.ruff]
# Target Python version
target-version = "py312"
# Line length - restored from old config
line-length = 120
# Indent width
indent-width = 4

# Exclude common directories - restored from old config
exclude = [
".bzr",
".direnv",
".eggs",
".git",
".git-rewrite",
".hg",
".ipynb_checkpoints",
".mypy_cache",
".nox",
".pants.d",
".pyenv",
".pytest_cache",
".pytype",
".ruff_cache",
".svn",
".tox",
".venv",
".vscode",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"site-packages",
"venv",
]

[tool.ruff.lint]
# Select a comprehensive set of rules
# Based on recommended practices from Ruff documentation
select = [
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"UP", # pyupgrade
]

# Common ignores for web development
ignore = [
"E501", # line too long (handled by formatter)
"B008", # do not perform function calls in argument defaults (common in FastAPI)
]

# Allow fixing all enabled rules
fixable = ["ALL"]

# Allow unused variables when underscore-prefixed - restored from old config
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"

[tool.ruff.format]
# Modern formatting options
quote-style = "double"
indent-style = "space"
# Format docstring code blocks
docstring-code-format = true
# Restored from old config
skip-magic-trailing-comma = false
line-ending = "auto"

[tool.ruff.lint.isort]
# Enhanced isort configuration
known-first-party = ["src"]
# Make sure we correctly order the import sections
section-order = [
"future",
"standard-library",
"third-party",
"first-party",
"local-folder",
]
# Add a trailing comma to imports split across multiple lines
split-on-trailing-comma = true
# Combine import statements for the same module
combine-as-imports = true

[project]
name = "watchflow"
version = "0.1.0"
Expand All @@ -96,17 +8,6 @@ license = {text = "Apache Software License 2.0"}
authors = [
{name = "Dimitris Kargatzis", email = "[email protected]"},
]
keywords = ["github", "governance", "ai", "protection", "rules", "enforcement", "collaboration"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.12",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Software Development :: Quality Assurance",
]

dependencies = [
"fastapi[standard]>=0.104.0",
"uvicorn[standard]>=0.24.0",
Expand All @@ -131,120 +32,80 @@ dev = [
"pytest>=7.4.0",
"pytest-asyncio>=0.21.0",
"pytest-cov>=4.1.0",
"black>=23.0.0",
"isort>=5.12.0",
"flake8>=6.0.0",
"respx>=0.20.0",
"mypy>=1.7.0",
"pre-commit>=3.5.0",
"ruff>=0.1.0", # Replaces black, isort, flake8
]

docs = [
"mkdocs>=1.5.0",
"mkdocs-material>=9.5.0",
"mkdocs-git-revision-date-localized-plugin>=1.2.0",
"mkdocs-minify-plugin>=0.7.0",
"pymdown-extensions>=10.0",
]

[project.urls]
Homepage = "https://github.com/warestack/watchflow"
Documentation = "https://docs.watchflow.dev"
Repository = "https://github.com/warestack/watchflow"
Issues = "https://github.com/warestack/watchflow/issues"

[project.scripts]
watchflow = "src.main:app"

[tool.black]
line-length = 88
target-version = ['py312']
include = '\.pyi?$'
extend-exclude = '''
/(
# directories
\.eggs
| \.git
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| build
| dist
)/
'''
# --- RUFF CONFIGURATION (The Enforcer) ---
[tool.ruff]
target-version = "py312"
line-length = 120
indent-width = 4
exclude = [
".git", ".mypy_cache", ".pytest_cache", ".ruff_cache", ".venv", "venv", "__pypackages__",
]

[tool.ruff.lint]
# E/F: Core Python errors
# I: Import sorting (isort replacement)
# B: Bugbear (catches common bugs)
# UP: Pyupgrade (modernizes syntax)
# C4: Comprehensions
# SIM: Simplify (suggests pythonic refactors)
# TCH: Type Checking (enforces specific typing blocks)
select = ["E", "F", "I", "B", "UP", "C4", "SIM", "TCH"]
ignore = [
"E501", # Line too long (handled by formatter)
"B008", # Do not perform function calls in argument defaults (FastAPI Dependency Pattern)
]
fixable = ["ALL"]

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"
docstring-code-format = true

[tool.isort]
profile = "black"
multi_line_output = 3
line_length = 88
known_first_party = ["src"]
[tool.ruff.lint.isort]
known-first-party = ["src"]
combine-as-imports = true

# --- MYPY CONFIGURATION (The Type Cop) ---
[tool.mypy]
python_version = "3.12"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
disallow_untyped_defs = true # No dynamic functions allowed
disallow_incomplete_defs = true # Must type all args
check_untyped_defs = true
disallow_untyped_decorators = true
disallow_untyped_decorators = false # Allow untyped decorators (needed for FastAPI/LangChain)
no_implicit_optional = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_no_return = true
warn_unreachable = true
strict_equality = true

# --- PYTEST CONFIGURATION ---
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py", "*_test.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
"--strict-markers",
"--strict-config",
"--cov=src",
"--cov-report=term-missing",
"--cov-report=html",
"--cov-report=xml",
]
asyncio_mode = "auto"


[tool.coverage.run]
source = ["src"]
omit = [
"*/tests/*",
"*/test_*",
"*/__pycache__/*",
"*/migrations/*",
]

[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"if self.debug:",
"if settings.DEBUG",
"raise AssertionError",
"raise NotImplementedError",
"if 0:",
"if __name__ == .__main__.:",
"class .*\\bProtocol\\):",
"@(abc\\.)?abstractmethod",
]

[tool.uv]
dev-dependencies = [
"pytest>=7.4.0",
"pytest-asyncio>=0.21.0",
"pytest-cov>=4.1.0",
"black>=23.0.0",
"isort>=5.12.0",
"flake8>=6.0.0",
"mypy>=1.7.0",
"pre-commit>=3.5.0",
"mkdocs-material>=9.5.0",
"mkdocs-git-revision-date-localized-plugin>=1.2.0",
"mkdocs-minify-plugin>=0.7.0",
"pymdown-extensions>=10.0",
"ruff>=0.1.0",
]
Comment on lines 103 to 111
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

respx is missing from tool.uv.dev-dependencies.

The respx package was added to project.optional-dependencies.dev (line 35) but not to tool.uv.dev-dependencies. If developers use uv sync without --all-extras, respx won't be installed, potentially causing test failures locally.

Proposed fix
 [tool.uv]
 dev-dependencies = [
     "pytest>=7.4.0",
     "pytest-asyncio>=0.21.0",
     "pytest-cov>=4.1.0",
+    "respx>=0.20.0",
     "mypy>=1.7.0",
     "pre-commit>=3.5.0",
     "ruff>=0.1.0",
 ]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[tool.uv]
dev-dependencies = [
"pytest>=7.4.0",
"pytest-asyncio>=0.21.0",
"pytest-cov>=4.1.0",
"black>=23.0.0",
"isort>=5.12.0",
"flake8>=6.0.0",
"mypy>=1.7.0",
"pre-commit>=3.5.0",
"mkdocs-material>=9.5.0",
"mkdocs-git-revision-date-localized-plugin>=1.2.0",
"mkdocs-minify-plugin>=0.7.0",
"pymdown-extensions>=10.0",
"ruff>=0.1.0",
]
[tool.uv]
dev-dependencies = [
"pytest>=7.4.0",
"pytest-asyncio>=0.21.0",
"pytest-cov>=4.1.0",
"respx>=0.20.0",
"mypy>=1.7.0",
"pre-commit>=3.5.0",
"ruff>=0.1.0",
]
🤖 Prompt for AI Agents
In `@pyproject.toml` around lines 103 - 111, The tool.uv.dev-dependencies list is
missing the respx package (it exists in project.optional-dependencies.dev), so
add "respx" to the tool.uv.dev-dependencies array to ensure uv sync installs it
by default; update the tool.uv.dev-dependencies entry (referencing the
tool.uv.dev-dependencies section) to include respx with the same version
constraint used in project.optional-dependencies.dev (or a compatible one) so
local test runs that use uv without --all-extras have respx available.

2 changes: 1 addition & 1 deletion src/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
# Watchflow application package
# App package—root for imports, keep minimal.
2 changes: 1 addition & 1 deletion src/agents/feasibility_agent/agent.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Rule Feasibility Agent implementation with error handling and retry logic.
Rule Feasibility Agent implementation with error handling and retry logic.
"""

import asyncio
Expand Down
Loading
Loading