Skip to content
Merged
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
31 changes: 31 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
version: 2
updates:
- package-ecosystem: uv
directory: /
schedule:
interval: cron
cronjob: 42 4 * * *
timezone: Europe/Warsaw
open-pull-requests-limit: 1
versioning-strategy: increase-if-necessary
allow:
- dependency-name: costs
dependency-type: all
- dependency-name: goal
dependency-type: all
- dependency-name: pfix
dependency-type: all
- dependency-name: clickmd
dependency-type: all
- dependency-name: code2llm
dependency-type: all
groups:
internal-packages:
patterns:
- costs
- goal
- pfix
- clickmd
- code2llm
commit-message:
prefix: deps
35 changes: 35 additions & 0 deletions .github/internal-dependencies.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"schema": "goal.internal-dependencies/v1",
"packages": [
{
"name": "costs",
"repository": "semcod/costs",
"registry": "pypi",
"versioning": "semver"
},
{
"name": "goal",
"repository": "semcod/goal",
"registry": "pypi",
"versioning": "semver"
},
{
"name": "pfix",
"repository": "semcod/pfix",
"registry": "pypi",
"versioning": "semver"
},
{
"name": "clickmd",
"repository": "semcod/clickmd",
"registry": "pypi",
"versioning": "semver"
},
{
"name": "code2llm",
"repository": "semcod/code2llm",
"registry": "pypi",
"versioning": "semver"
}
]
}
36 changes: 36 additions & 0 deletions .github/workflows/internal-dependency-freshness.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Internal dependency freshness

on:
schedule:
- cron: "47 5 * * *"
workflow_dispatch:
pull_request:
paths:
- pyproject.toml
- uv.lock
- .github/internal-dependencies.json
- .github/workflows/internal-dependency-freshness.yml

permissions:
contents: read

jobs:
freshness:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: "3.12"
- name: Install released checker
run: python -m pip install "goal==2.2.0"
- name: Verify published stable targets
run: goal dependencies --catalog .github/internal-dependencies.json --check > dependency-freshness.json
- name: Retain freshness evidence
if: always()
uses: actions/upload-artifact@v4
with:
name: dependency-freshness
path: dependency-freshness.json
if-no-files-found: ignore
47 changes: 47 additions & 0 deletions .github/workflows/test-locked.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Locked tests

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:

permissions:
contents: read

jobs:
supported_python:
name: test (${{ matrix.python-version }})
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.13"]
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: ${{ matrix.python-version }}
- run: python -m pip install uv
- name: Install OCR runtime for integration tests
run: |
sudo apt-get update
sudo apt-get install --no-install-recommends -y tesseract-ocr tesseract-ocr-eng tesseract-ocr-pol
- name: Install locked test dependencies
run: uv sync --locked --extra dev --extra web --extra diagnose --python "${{ matrix.python-version }}"
- name: Test supported Python versions
run: uv run --no-sync python -m pytest -q

test:
name: test
needs: supported_python
if: always()
runs-on: ubuntu-latest
timeout-minutes: 2
steps:
- name: Require every supported Python job to pass
env:
MATRIX_RESULT: ${{ needs.supported_python.result }}
run: test "$MATRIX_RESULT" = success
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -362,3 +362,7 @@ Zobacz [TODO.md](TODO.md).
## License

Licensed under Apache-2.0.

## Dependency maintenance

See [dependency updates and Python tool groups](docs/dependencies.md) for locked tests, daily updates and freshness checks.
32 changes: 32 additions & 0 deletions docs/dependencies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Internal dependency updates

This repository owns its dependency configuration and this guide. The shared checker is maintained in [semcod/goal](https://github.com/semcod/goal/blob/84f18540d14c24cc8ff5b7f202d2874344779ecc/docs/internal-dependencies.md). Documentation follows the repository ownership principle in [wellmanifest/docs](https://github.com/wellmanifest/docs/blob/f64de5806577769672ebc1730d2e144b4c7671ec/README.md).

## Python support and tools

Application Python support remains `>=3.10,<3.14`. Goal is used as a development/release tool; source inspection found no Goal imports or executable invocation in the application Python code. Its old declarations (dev) moved to an `automation` dependency group requiring Python >=3.12. The normal dev/test installation remains usable on the application's minimum Python version.

```sh
uv sync --locked --extra dev
uv sync --locked --group automation --python 3.12
```

The second command selects an automation environment; use a separate UV_PROJECT_ENVIRONMENT when keeping application and tool environments side by side. `imgl` itself is excluded from the registry catalog when it is the local editable package.

## Daily updates and verification

[Dependabot configuration](../.github/dependabot.yml) checks the explicit internal package allowlist daily, including weekends, and groups updates in one PR. It includes transitive dependencies and may widen a manifest constraint when needed. Local or Git sources require separate review.

[Freshness CI](../.github/workflows/internal-dependency-freshness.yml) compares uv.lock with the highest published stable three-part versions using Goal 2.2.0. It runs daily, manually and on dependency PRs, has read-only repository permissions and retains JSON evidence. Resolver failures and mismatched targets stay visible. A successful audit says nothing about an already installed development or production environment.

[Locked tests](../.github/workflows/test-locked.yml) run on Python 3.10 and 3.13 before merge. Update creation does not grant merge approval. The `>=` declarations alone do not refresh uv.lock; environments must be synchronized after a tested update is merged.

## Delivery record

This change updates the internal packages to the registry targets observed on 2026-09-05, preserves application Python support and adds the scheduled checks above. Test and publication results are recorded in this repository's PR and Actions checks. The ecosystem rollout history is maintained in [costs documentation](https://github.com/semcod/costs/tree/main/docs/dependencies).

The test configuration exposes the repository-owned MCP adapter source for its execution-permission test. Optional control packages remain optional. Timestamp generation uses `timezone.utc`, which supports the declared Python 3.10 minimum.

The test runner installs the system Tesseract executable and English/Polish language data before the OCR/web integration tests. The Python `ocr` extra supplies the wrapper only. On Debian/Ubuntu, install `tesseract-ocr tesseract-ocr-eng tesseract-ocr-pol` before running this suite locally.

The `main-supervised-autonomy` GitHub ruleset requires a successful `test` check and an independent approval of the latest push. The aggregate `test` job fails unless every Python matrix job succeeds. Merge uses the repository-required merge commit method after review.
4 changes: 2 additions & 2 deletions imgl/capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import os
import shutil
import subprocess
from datetime import UTC, datetime
from datetime import datetime, timezone
from pathlib import Path


Expand Down Expand Up @@ -77,7 +77,7 @@ def default_capture_path(out: str | Path | None = None) -> Path:
path = Path(out).expanduser()
path.parent.mkdir(parents=True, exist_ok=True)
return path
ts = datetime.now(UTC).strftime("%Y%m%d_%H%M%S")
ts = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
path = Path.home() / ".imgl" / "captures" / f"screen_{ts}.png"
path.parent.mkdir(parents=True, exist_ok=True)
return path
Expand Down
4 changes: 2 additions & 2 deletions imgl/export/vql_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import json
import os
import sys
from datetime import UTC, datetime
from datetime import datetime, timezone
from pathlib import Path
from typing import Any

Expand Down Expand Up @@ -83,7 +83,7 @@ def scene_to_vql(
"detect_source": scene.metadata.get("detect_source", ""),
"ocr_backend": scene.metadata.get("ocr_backend", ""),
"lang": scene.metadata.get("lang", ""),
"analyzed_at": datetime.now(UTC).isoformat(),
"analyzed_at": datetime.now(timezone.utc).isoformat(),
}
capture = scene.metadata.get("capture")
if isinstance(capture, dict) and capture:
Expand Down
11 changes: 10 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ full = [
]
dev = [
"pytest>=8.0",
"goal>=2.1.0",
"costs>=0.1.20",
"pfix>=0.1.60",
# dev environments should exercise the OCR path
Expand Down Expand Up @@ -107,3 +106,13 @@ max_commits = 500

# Cost thresholds for badge colors (USD)
badge_color_thresholds = { low = 1.0, medium = 5.0, high = 10.0, critical = 50.0 }

[tool.uv.dependency-groups]
automation = {requires-python = ">=3.12"}

[dependency-groups]
automation = ["goal>=2.2.0"]

[tool.pytest.ini_options]
# Test the repository-owned MCP adapter without installing the optional control stack.
pythonpath = ["packages/mcp2imgl/src"]
Loading
Loading