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
2 changes: 1 addition & 1 deletion .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ jobs:
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
if: github.ref == 'refs/heads/main'
if: github.ref == 'refs/heads/main' && github.repository == 'warestack/watchflow'
steps:
# Deploy to GitHub Pages
- name: "Deploy to GitHub Pages"
Expand Down
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:

Choose a reason for hiding this comment

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

medium

The comment # Configuration for pre-commit hooks was removed, but the other comments explaining individual hooks were also removed. It would be beneficial to keep concise comments for each hook, especially for check-yaml and check-json, to explain their purpose.

# 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

Comment on lines +16 to 25
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

ruff-pre-commit latest version 2024 2025

💡 Result:

The latest ruff-pre-commit release is v0.14.13 (released Jan 15, 2026). [1]

For context, earlier recent releases include v0.14.11 (Jan 8, 2026) and v0.14.10 (Dec 18, 2025). [1][2]

Sources:

  • GitHub releases for astral-sh/ruff-pre-commit. [1]
  • ruff PyPI page (example pre-commit rev references). [2]

🏁 Script executed:

# Search for Ruff configuration files in the repository
fd -e toml -e cfg | grep -E "(pyproject|ruff|setup)" | head -20

Repository: warestack/watchflow

Length of output: 182


🏁 Script executed:

# Look for any ruff configuration in common locations
find . -maxdepth 2 -type f \( -name "pyproject.toml" -o -name "ruff.toml" -o -name "setup.cfg" -o -name ".pre-commit-config.yaml" \)

Repository: warestack/watchflow

Length of output: 105


🏁 Script executed:

cat pyproject.toml

Repository: warestack/watchflow

Length of output: 2990


🏁 Script executed:

cat .pre-commit-config.yaml

Repository: warestack/watchflow

Length of output: 898


🌐 Web query:

ruff-format hook when introduced ruff-pre-commit v0.3.0 release date

💡 Result:

  • ruff-pre-commit v0.3.0 release date: Feb 29, 2024. [1]

  • ruff-format pre-commit hook: documented in the ruff-pre-commit README (the formatter hook "ruff-format" / formatter support is noted as available once Ruff added a formatter — referenced in the ruff-pre-commit repo README). Usage/examples appear in docs and issues from early 2024. [2][3]

Sources:

  1. PyPI release files for ruff 0.3.0 (uploaded Feb 29, 2024). [turn6search5]
  2. ruff-pre-commit README showing the ruff-format hook. [turn8search1]
  3. ruff-pre-commit issue / discussion showing ruff-format in use (Jan–Feb 2024). [turn8search6]

Update ruff-pre-commit from v0.3.0 to a recent version.

v0.3.0 (released Feb 2024) is significantly outdated—the latest version is v0.14.13 (Jan 2026). The repository's pyproject.toml specifies ruff>=0.1.0 and includes modern formatter configuration ([tool.ruff.format] with options like docstring-code-format). Update to a recent release to ensure the formatter configuration is fully supported and to receive bug fixes and improvements from the past 2 years of development.

🤖 Prompt for AI Agents
In @.pre-commit-config.yaml around lines 16 - 25, The pre-commit hook for Ruff
is pinned to an old rev (rev: v0.3.0); update the ruff-pre-commit hook to a
recent release (e.g., rev: v0.14.13) so the formatter options in pyproject.toml
(like [tool.ruff.format] and docstring-code-format) are supported and you get
recent fixes; locate the block with repo:
https://github.com/astral-sh/ruff-pre-commit and the hooks with id: ruff and id:
ruff-format and replace the rev value accordingly, keeping the existing args
(--fix, --exit-non-zero-on-fix) and hook ids unchanged.

# 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.
2 changes: 1 addition & 1 deletion docs/benchmarks.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Watchflow's agentic approach to DevOps governance has shown promising results in

### Context Dependency in Enterprise Policies

Our analysis of 70+ enterprise policies from major tech companies revealed a critical insight: **85% of real-world governance policies require context** and cannot be effectively enforced with traditional static rules.
Our analysis of 70 + enterprise policies from major tech companies revealed a critical insight: **85% of real-world governance policies require context** and cannot be effectively enforced with traditional static rules.
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

Unintentional typo introduces inconsistency.

The change from 70+ to 70 + appears accidental. Line 58 still uses 70+ (without space), creating inconsistency. The space changes the meaning from "more than 70" to a mathematical expression.

Suggested fix
-Our analysis of 70 + enterprise policies from major tech companies revealed a critical insight: **85% of real-world governance policies require context** and cannot be effectively enforced with traditional static rules.
+Our analysis of 70+ enterprise policies from major tech companies revealed a critical insight: **85% of real-world governance policies require context** and cannot be effectively enforced with traditional static rules.
📝 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
Our analysis of 70 + enterprise policies from major tech companies revealed a critical insight: **85% of real-world governance policies require context** and cannot be effectively enforced with traditional static rules.
Our analysis of 70+ enterprise policies from major tech companies revealed a critical insight: **85% of real-world governance policies require context** and cannot be effectively enforced with traditional static rules.
🤖 Prompt for AI Agents
In `@docs/benchmarks.md` at line 9, Replace the accidental "70 +" with the
intended "70+" to restore consistency with other occurrences (e.g., the later
"70+" at line 58) in the sentence "Our analysis of 70 + enterprise policies..."
so it reads "Our analysis of 70+ enterprise policies..." throughout the
document.


**Why this matters:**
- Traditional rules are binary (true/false) and miss nuanced scenarios
Expand Down
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: 45 additions & 176 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 @@ -124,127 +25,95 @@ dependencies = [
"boto3>=1.40.43",
"anthropic[vertex]>=0.69.0",
"langchain-google-vertexai>=2.1.2",
"giturlparse>=0.1.0",
"structlog>=24.1.0",
]

[project.optional-dependencies]
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
Comment on lines +37 to +40
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's locate and examine the pyproject.toml file
git ls-files | grep -E "pyproject\.toml$"

Repository: warestack/watchflow

Length of output: 77


🌐 Web query:

Ruff minimum version requirements [tool.ruff.format] indent-width docstring-code-format

💡 Result:

  • indent-width: supported in Ruff configuration (see Settings). [1]
  • docstring-code-format (and docstring-code-line-length): introduced via config PR (#8854); it's an opt-in formatter setting documented in the Ruff formatter docs. Use a Ruff build that includes PR #8854 (see the PR/commit history) or any recent release that contains the formatter updates. [2][3]

Sources:
[1] Ruff Settings — indent-width. [docs.astral.sh/ruff/settings] (docs.astral.sh)
[2] The Ruff formatter docs (docstring-code-format / docstring-code-line-length). [docs.astral.sh/ruff/formatter] (docs.astral.sh)
[3] GitHub: config: add new docstring-code-format knob (PR/commit reference). (git.joshthomas.dev)

If you want I can look up the exact Ruff release/version that first included PR #8854 and give the minimum version number.

Citations:


🌐 Web query:

Ruff changelog version 0.1.0 format configuration support

💡 Result:

Short answer: In Ruff 0.1.0 the old "format" configuration was removed — you must use the new "output-format" option (and RUFF_OUTPUT_FORMAT / --output-format) to configure output format. [1][2]

Sources:

  • Ruff CHANGELOG (0.1.0) — notes that the deprecated format setting was removed and to use output-format / RUFF_OUTPUT_FORMAT / --output-format instead. [1]
  • Ruff 0.1.0 release summary (release notes). [2]

🌐 Web query:

Ruff rule selectors TCH when introduced minimum version

💡 Result:

Short answer: The "TCH" selector comes from Ruff's flake8-type-checking rules (used in 2023) and was remapped to "TC" in Ruff v0.8.0 — Ruff 0.8.0 is the minimum release that documents the remapping (TCH -> TC) and emits a deprecation warning when you use the old TCH codes. [1][2]

Sources:

  • Ruff v0.8.0 release notes (remapped flake8-type-checking: TCH -> TC). [1]
  • GitHub issue showing TCH usage/discussion (Dec 2023). [2]

🏁 Script executed:

cat pyproject.toml

Repository: warestack/watchflow

Length of output: 2990


🌐 Web query:

Ruff [tool.ruff.format] section minimum version when introduced

💡 Result:

The [tool.ruff.format] section was introduced with the Ruff formatter (beta) — added in Ruff v0.1.2 (Oct 24, 2023). [1][2]

Sources:

  • Ruff v0.1.2 release notes (announces the Beta formatter). [1]
  • Ruff configuration / formatter docs showing [tool.ruff.format] settings. [2]

🌐 Web query:

Ruff 0.1.0 vs 0.2.0 vs 0.3.0 format section support release notes

💡 Result:

Summary of format-section support by Ruff releases

  • v0.1.0 — initial Ruff formatter and basic pyproject configuration support (formatter settings live under [tool.ruff.format] / [format]). [1][2]

  • v0.2.x (notably 0.2.1 / 0.2.2) — formatter feature additions:

    • Added range formatting (ruff format --range) to format specific line ranges.
    • Formatting improvements for module-level docstrings and not trimming last empty line in docstrings.
    • Early f-string formatting support in preview builds and other formatter fixes. [2]
  • v0.3.0 — first stable/stabilizing formatter release: introduced the “Ruff formatter 2024.2” style and added a lint rule detecting invalid formatter-suppression comments; continued formatter stabilizations and style changes. [3]

Sources

  1. Ruff formatter docs (configuration / [tool.ruff.format]). [docs.astral.sh]. (docs.astral.sh)
  2. Ruff changelog (0.2.x — range formatting, docstring fixes, f-string preview). (fossies.org)
  3. Ruff v0.3.0 release summary (formatter 2024.2 style, suppression-comment rule). (newreleases.io)

If you want, I can copy the exact pyproject keys available in each version or link the specific GitHub changelog entries.

Citations:


🌐 Web query:

Ruff docstring-code-format PR #8854 which release version minimum

💡 Result:

The feature from PR #8854 (docstring-code-format) first appears in ruff v0.1.8. [1][2]

Sources:

  • ruff changelog (v0.1.8) — lists "Add docstring-code-format knob" (#8854). [1]
  • ruff CHANGELOG in repo — same entry. [2]

🌐 Web query:

Ruff changelog 0.1.2 0.1.3 0.1.4 0.1.5 0.2.0 docstring-code-format when added

💡 Result:

Summary: The docstring-code-format option was introduced in Ruff v0.1.8 (so it was not present in v0.1.2–v0.1.5 and is available in later releases, including 0.2.0). [1][2][3]

Sources:

  • PR adding the config knob (config: add new docstring-code-format (#8854)). [1]
  • Ruff 0.1.x changelog noting "Add docstring-code-format knob" in v0.1.8. [2]
  • PyPI upload metadata for ruff 0.1.8 (upload date Dec 13, 2023). [3]

Bump Ruff minimum version to 0.1.8 to support docstring-code-format.

The configuration uses docstring-code-format = true in [tool.ruff.format], which was introduced in Ruff v0.1.8. Setting ruff>=0.1.0 creates a version mismatch—if an older version is installed, config parsing will fail. Update both occurrences (lines 35–38 and in [tool.uv].dev-dependencies) to ruff>=0.1.8.

🤖 Prompt for AI Agents
In `@pyproject.toml` around lines 35 - 38, Update the declared Ruff minimum
version to match the configuration: replace the existing "ruff>=0.1.0"
dependency entries with "ruff>=0.1.8" wherever Ruff is listed (the dependency
line in the main dependencies block and the ruff entry under
[tool.uv].dev-dependencies) so the parser supports the docstring-code-format
setting; ensure both occurrences are changed to "ruff>=0.1.8".

]

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",
"mkdocs-minify-plugin>=0.8.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",
"giturlparse>=0.1.0",
]
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.
Loading