Skip to content

Commit 598b7be

Browse files
refactoring
1 parent 2c593db commit 598b7be

11 files changed

Lines changed: 387 additions & 90 deletions

File tree

.dockerignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
.git
2+
.venv
3+
venv
4+
__pycache__
5+
*.pyc
6+
.pytest_cache
7+
.mypy_cache
8+
.ruff_cache
9+
.coverage
10+
htmlcov
11+
dist
12+
build
13+
*.egg-info
14+
.env
15+
.env.*
16+
! .env.example
17+
*.log
18+
profile.stats

.taskill/state.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"last_run_iso": "2026-04-25T18:22:34.274854+00:00",
3+
"last_commit_sha": "2c593db97fdd03d3f1d9ae0804bb852c01e6526a",
4+
"last_coverage_pct": null,
5+
"last_failed_tests": null,
6+
"last_sumd_hash": "4ead77e705653edc",
7+
"last_todo_hash": "0ca9717777b64a6b",
8+
"last_readme_hash": "85f1f3e604dd2c09",
9+
"file_mtimes": {
10+
"SUMD.md": 1777110970.3002408,
11+
"SUMR.md": 1777110974.7123258
12+
}
13+
}

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,17 @@
106106

107107
## [Unreleased]
108108

109+
110+
- feat(pyqual): extract pipeline stages to reusable plugins in llx/pyqual_plugins
111+
- feat(pyqual): make publish idempotent with auto version bump
112+
- feat(config): deep code analysis engine with supporting modules
113+
- feat(config): new API capabilities
114+
- feat(goal): CLI interface improvements
115+
- test(pyqual): automate pyqual GitHub sync
116+
- fix(ci): address pyqual CI failures
117+
- chore(release): bump version for release and add build/publish stages
118+
- refactor(docs,examples,tests,llx): reorganize code analysis engine, configuration management, and quality metrics modules
119+
109120
## [0.1.60] - 2026-04-25
110121

111122
### Docs

Dockerfile

Lines changed: 14 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,35 @@
11
# Multi-stage build for llx
22
FROM python:3.11-slim AS builder
33

4-
# Set build arguments
5-
ARG BUILD_DATE
6-
ARG VERSION
7-
ARG VCS_REF
8-
9-
# Labels
10-
LABEL maintainer="Tom Sapletta <tom@sapletta.org>"
11-
LABEL org.label-schema.build-date=$BUILD_DATE
12-
LABEL org.label-schema.name="llx"
13-
LABEL org.label-schema.description="Intelligent LLM model router driven by real code metrics"
14-
LABEL org.label-schema.url="https://github.com/wronai/llx"
15-
LABEL org.label-schema.vcs-ref=$VCS_REF
16-
LABEL org.label-schema.vcs-url="https://github.com/wronai/llx"
17-
LABEL org.label-schema.vendor="Tom Sapletta"
18-
LABEL org.label-schema.version=$VERSION
19-
204
# Set environment variables
215
ENV PYTHONUNBUFFERED=1 \
226
PYTHONDONTWRITEBYTECODE=1 \
23-
PIP_NO_CACHE_DIR=1 \
7+
PIP_NO_CACHE_DIR=0 \
248
PIP_DISABLE_PIP_VERSION_CHECK=1
259

2610
# Install system dependencies
2711
RUN apt-get update && apt-get install -y \
2812
build-essential \
2913
curl \
3014
git \
31-
jq \
32-
netcat-openbsd \
33-
ca-certificates \
3415
&& rm -rf /var/lib/apt/lists/*
3516

36-
# Create app user
37-
RUN groupadd -r llx && useradd -r -g llx llx
38-
39-
# Set work directory
4017
WORKDIR /app
4118

42-
# Copy requirements first for better caching
19+
# Copy pyproject.toml and requirements for caching
20+
COPY pyproject.toml .
4321
COPY requirements.txt .
44-
COPY requirements-dev.txt .
4522

46-
# Install Python dependencies
47-
RUN pip install --upgrade pip && \
48-
pip install -r requirements.txt && \
49-
pip install -r requirements-dev.txt
23+
# Install dependencies with cache mount
24+
RUN --mount=type=cache,target=/root/.cache/pip \
25+
pip install --upgrade pip && \
26+
pip install -r requirements.txt
5027

5128
# Copy application code
5229
COPY . .
5330

54-
# Install llx in development mode
55-
RUN pip install -e .
31+
# Install llx (without dev deps for production-ready builder)
32+
RUN pip install .
5633

5734
# Production stage
5835
FROM python:3.11-slim AS production
@@ -66,7 +43,6 @@ ENV PYTHONUNBUFFERED=1 \
6643
RUN apt-get update && apt-get install -y \
6744
curl \
6845
jq \
69-
netcat-openbsd \
7046
ca-certificates \
7147
&& rm -rf /var/lib/apt/lists/* && \
7248
apt-get clean
@@ -78,22 +54,20 @@ RUN groupadd -r llx && useradd -r -g llx llx
7854
RUN mkdir -p /app/logs /app/cache /app/data && \
7955
chown -R llx:llx /app
8056

81-
# Copy from builder stage
82-
COPY --from=builder --chown=llx:llx /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
83-
COPY --from=builder --chown=llx:llx /usr/local/bin /usr/local/bin
84-
COPY --from=builder --chown=llx:llx /app /app
57+
# Copy from builder stage - only what's necessary
58+
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
59+
COPY --from=builder /usr/local/bin /usr/local/bin
60+
COPY --from=builder --chown=llx:llx /app/llx /app/llx
61+
COPY --from=builder --chown=llx:llx /app/pyproject.toml /app/pyproject.toml
8562

8663
# Switch to app user
8764
USER llx
88-
89-
# Set work directory
9065
WORKDIR /app
9166

9267
# Health check
9368
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
9469
CMD curl -f http://localhost:4000/health || exit 1
9570

96-
# Expose port
9771
EXPOSE 4000
9872

9973
# Default command

Makefile

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,15 @@ help:
4444
# Installation
4545
install:
4646
@echo "📦 Installing llx..."
47-
python -m venv .venv
48-
.venv/bin/pip install --upgrade pip
49-
.venv/bin/pip install -e .
50-
.venv/bin/pip install -r requirements-dev.txt
47+
@if command -v uv > /dev/null 2>&1; then \
48+
uv venv; \
49+
.venv/bin/pip install --upgrade pip; \
50+
uv pip install -e ".[dev]"; \
51+
else \
52+
python -m venv .venv; \
53+
.venv/bin/pip install --upgrade pip; \
54+
.venv/bin/pip install -e ".[dev]"; \
55+
fi
5156
@echo "✅ Installation completed!"
5257
@echo "Run 'source .venv/bin/activate' to activate the virtual environment"
5358

@@ -93,15 +98,15 @@ test-docker:
9398
docker run --rm llx-test .venv/bin/python -m pytest tests/ -v
9499

95100
lint:
96-
@echo "🔍 Running linting..."
97-
.venv/bin/python -m flake8 llx/ --max-line-length=100 --ignore=E203,W503
101+
@echo "🔍 Running linting with ruff..."
102+
.venv/bin/python -m ruff check llx/
103+
.venv/bin/python -m ruff check tests/
98104
.venv/bin/python -m mypy llx/ --ignore-missing-imports
99-
.venv/bin/python -m black --check llx/
100105

101106
format:
102-
@echo "📝 Formatting code..."
103-
.venv/bin/python -m black llx/
104-
.venv/bin/python -m isort llx/
107+
@echo "📝 Formatting code with ruff..."
108+
.venv/bin/python -m ruff format llx/
109+
.venv/bin/python -m ruff format tests/
105110

106111
# Docker commands
107112
docker-dev:
@@ -231,8 +236,8 @@ ci-test:
231236
.venv/bin/python -m pytest tests/ -v --cov=llx --cov-report=xml --cov-report=html
232237

233238
ci-lint:
234-
@echo "🔍 CI linting..."
235-
.venv/bin/python -m flake8 llx/ --max-line-length=100 --ignore=E203,W503 --output-format=github
239+
@echo "🔍 CI linting with ruff..."
240+
.venv/bin/python -m ruff check llx/ --format=github
236241
.venv/bin/python -m mypy llx/ --ignore-missing-imports --junit-xml test-results.xml
237242

238243
ci-build:

README.md

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010

1111
## AI Cost Tracking
1212

13-
![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.1.60-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
14-
![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-26.9h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
13+
![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.1.31-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
14+
![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-28.4h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
1515

16-
- 🤖 **LLM usage:** $7.5000 (73 commits)
17-
- 👤 **Human dev:** ~$2687 (26.9h @ $100/h, 30min dedup)
16+
- 🤖 **LLM usage:** $7.5000 (74 commits)
17+
- 👤 **Human dev:** ~$2835 (28.4h @ $100/h, 30min dedup)
1818

1919
Generated on 2026-04-25 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
2020

@@ -266,6 +266,74 @@ llx init # Creates llx.toml with defaults
266266
267267
Environment variables: `LLX_LITELLM_URL`, `LLX_DEFAULT_TIER`, `LLX_PROXY_PORT`, `LLX_VERBOSE`.
268268
269+
## Planfile Integration
270+
271+
llx supports planfile.yaml format (redsl-generated) for sequential task execution:
272+
273+
```python
274+
from llx.planfile import execute_strategy
275+
276+
# Execute planfile.yaml (supports V1, V2, and redsl formats)
277+
results = execute_strategy(
278+
"planfile.yaml",
279+
project_path=".",
280+
dry_run=True
281+
)
282+
283+
# Process results
284+
for result in results:
285+
print(f"{result.task_name}: {result.status}")
286+
```
287+
288+
**CLI usage:**
289+
```bash
290+
# Proste lokalne wykonanie (nowa komenda)
291+
llx plan run . # Uruchom planfile.yaml
292+
llx plan run . --tier free # Z konkretnym tierem modelu
293+
llx plan run . --sprint 1 # Tylko sprint 1
294+
llx plan run . --dry-run # Symulacja bez wykonywania
295+
296+
# Generowanie i recenzja
297+
llx plan generate strategy.yaml --output generated/
298+
llx plan review strategy.yaml --project .
299+
300+
# Tworzenie ticketów w GitHub (wymaga zewnętrznego planfile)
301+
llx plan execute strategy.yaml --project . --dry-run
302+
```
303+
304+
**Supported formats:**
305+
- **V1**: Tasks defined separately in `task_patterns`
306+
- **V2**: Tasks embedded directly in sprints
307+
- **planfile.yaml**: Redsl-generated format with flat tasks list and sprint task_patterns
308+
309+
See `llx/planfile/README_SIMPLIFIED.md` for details.
310+
311+
## Testql Integration
312+
313+
llx can execute tasks generated by testql audits:
314+
315+
```bash
316+
# Generate planfile from testql audit
317+
testql audit --output .testql/dom-audit-planfile.json
318+
319+
# Convert to planfile.yaml format (if needed)
320+
# Then execute with llx
321+
llx plan execute planfile.yaml --project . --dry-run
322+
```
323+
324+
**Example workflow:**
325+
```bash
326+
# 1. Run testql audit
327+
testql audit --path ./my-project
328+
329+
# 2. Generate planfile.yaml from audit results
330+
# (use redsl or manual conversion)
331+
332+
# 3. Execute tasks with llx
333+
from llx.planfile import execute_strategy
334+
results = execute_strategy("planfile.yaml", project_path="./my-project")
335+
```
336+
269337
## Python API
270338
271339
```python
@@ -284,6 +352,8 @@ print(result.explain()) # Human-readable reasoning
284352
| [code2llm](https://github.com/wronai/code2llm) | Static analysis | CC, fan-out, cycles, hotspots |
285353
| [redup](https://github.com/semcod/redup) | Duplication detection | Groups, recoverable lines |
286354
| [vallm](https://github.com/semcod/vallm) | Code validation | Pass rate, issue count |
355+
| [planfile](https://github.com/semcod/planfile) | Strategy execution | Task execution, sprint management |
356+
| [testql](https://github.com/semcod/testql) | Quality testing | Audit integration, ticket generation |
287357
| **llx** | **Model routing + MCP server** | **Consumes all above** |
288358
289359
## Package structure
@@ -318,3 +388,20 @@ Full generated API inventory: `docs/README.md`.
318388
## License
319389
320390
Licensed under Apache-2.0.
391+
392+
<!-- taskill:status:start -->
393+
394+
## Status
395+
396+
_Last updated by [taskill](https://github.com/oqlos/taskill) at 2026-04-25 18:22 UTC_
397+
398+
| Metric | Value |
399+
|---|---|
400+
| HEAD | `2c593db` |
401+
| Coverage ||
402+
| Failing tests ||
403+
| Commits in last cycle | 0 |
404+
405+
> No commits or file changes since the last taskill run.
406+
407+
<!-- taskill:status:end -->

0 commit comments

Comments
 (0)