piloop 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- piloop-0.1.0/.github/ISSUE_TEMPLATE/1_bug_report.yml +32 -0
- piloop-0.1.0/.github/ISSUE_TEMPLATE/2_feature_request.yml +16 -0
- piloop-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- piloop-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +10 -0
- piloop-0.1.0/.github/dependabot.yml +18 -0
- piloop-0.1.0/.github/workflows/ci.yml +99 -0
- piloop-0.1.0/.github/workflows/release.yml +58 -0
- piloop-0.1.0/.github/workflows/sync.yml +34 -0
- piloop-0.1.0/.gitignore +13 -0
- piloop-0.1.0/.pre-commit-config.yaml +43 -0
- piloop-0.1.0/.python-version +1 -0
- piloop-0.1.0/AGENTS.md +48 -0
- piloop-0.1.0/CHANGELOG.md +36 -0
- piloop-0.1.0/CONTRIBUTING.md +134 -0
- piloop-0.1.0/LICENSE +21 -0
- piloop-0.1.0/Makefile +40 -0
- piloop-0.1.0/PKG-INFO +147 -0
- piloop-0.1.0/README.md +111 -0
- piloop-0.1.0/alembic.ini +5 -0
- piloop-0.1.0/docs/architecture/code-layout.mdx +82 -0
- piloop-0.1.0/docs/architecture/data-model.mdx +190 -0
- piloop-0.1.0/docs/architecture/extension-points.mdx +66 -0
- piloop-0.1.0/docs/architecture/overview.mdx +124 -0
- piloop-0.1.0/docs/architecture/run-lifecycle.mdx +82 -0
- piloop-0.1.0/docs/architecture/state-machines.mdx +94 -0
- piloop-0.1.0/docs/by-hand.mdx +192 -0
- piloop-0.1.0/docs/concepts/cost.mdx +79 -0
- piloop-0.1.0/docs/concepts/ideas-and-runs.mdx +114 -0
- piloop-0.1.0/docs/concepts/orchestrator.mdx +112 -0
- piloop-0.1.0/docs/concepts/projects.mdx +106 -0
- piloop-0.1.0/docs/concepts/roles.mdx +141 -0
- piloop-0.1.0/docs/concepts/session-capture.mdx +64 -0
- piloop-0.1.0/docs/concepts/tracks.mdx +76 -0
- piloop-0.1.0/docs/concepts/verdict.mdx +118 -0
- piloop-0.1.0/docs/docs.json +77 -0
- piloop-0.1.0/docs/favicon.svg +5 -0
- piloop-0.1.0/docs/guides/mcp-servers.mdx +92 -0
- piloop-0.1.0/docs/guides/reviewing.mdx +73 -0
- piloop-0.1.0/docs/guides/running-for-days.mdx +91 -0
- piloop-0.1.0/docs/guides/secrets.mdx +64 -0
- piloop-0.1.0/docs/guides/upgrading.mdx +81 -0
- piloop-0.1.0/docs/guides/watch.mdx +83 -0
- piloop-0.1.0/docs/images/watch-campaign.svg +249 -0
- piloop-0.1.0/docs/images/watch-candidates.svg +248 -0
- piloop-0.1.0/docs/images/watch-ideas.svg +249 -0
- piloop-0.1.0/docs/index.mdx +126 -0
- piloop-0.1.0/docs/quickstart.mdx +146 -0
- piloop-0.1.0/docs/reference/cli.mdx +285 -0
- piloop-0.1.0/docs/reference/configuration.mdx +233 -0
- piloop-0.1.0/docs/reference/environment.mdx +47 -0
- piloop-0.1.0/docs/reference/schema.mdx +233 -0
- piloop-0.1.0/docs/several-campaigns.mdx +58 -0
- piloop-0.1.0/install.sh +44 -0
- piloop-0.1.0/piloop/__init__.py +0 -0
- piloop-0.1.0/piloop/__main__.py +3 -0
- piloop-0.1.0/piloop/agents/__init__.py +1 -0
- piloop-0.1.0/piloop/agents/capture.py +118 -0
- piloop-0.1.0/piloop/agents/launcher.py +443 -0
- piloop-0.1.0/piloop/agents/prompts/research.md +229 -0
- piloop-0.1.0/piloop/agents/prompts/research_scout.md +129 -0
- piloop-0.1.0/piloop/agents/prompts/sql_procedures.md +295 -0
- piloop-0.1.0/piloop/agents/prompts/watchdog.md +30 -0
- piloop-0.1.0/piloop/agents/prompts/watchdog_incident.md +23 -0
- piloop-0.1.0/piloop/agents/prompts/watchdog_progress.md +25 -0
- piloop-0.1.0/piloop/agents/prompts/worker.md +94 -0
- piloop-0.1.0/piloop/agents/refill.py +33 -0
- piloop-0.1.0/piloop/agents/roles.py +214 -0
- piloop-0.1.0/piloop/agents/scout.py +159 -0
- piloop-0.1.0/piloop/campaign/__init__.py +1 -0
- piloop-0.1.0/piloop/campaign/ideas.py +347 -0
- piloop-0.1.0/piloop/campaign/inbox.py +235 -0
- piloop-0.1.0/piloop/campaign/project.py +242 -0
- piloop-0.1.0/piloop/campaign/spend.py +143 -0
- piloop-0.1.0/piloop/campaign/stop.py +147 -0
- piloop-0.1.0/piloop/campaign/templates/enwik8/.entire/.gitignore +5 -0
- piloop-0.1.0/piloop/campaign/templates/enwik8/.entire/settings.json +1 -0
- piloop-0.1.0/piloop/campaign/templates/enwik8/brief.md +32 -0
- piloop-0.1.0/piloop/campaign/templates/enwik8/compressor.py +13 -0
- piloop-0.1.0/piloop/campaign/templates/enwik8/evaluate.py +69 -0
- piloop-0.1.0/piloop/campaign/templates/enwik8/piloop.toml +31 -0
- piloop-0.1.0/piloop/campaign/templates/enwik8/pyproject.toml +5 -0
- piloop-0.1.0/piloop/campaign/templates/project/.entire/.gitignore +5 -0
- piloop-0.1.0/piloop/campaign/templates/project/.entire/settings.json +1 -0
- piloop-0.1.0/piloop/campaign/templates/project/brief.md +47 -0
- piloop-0.1.0/piloop/campaign/templates/project/evaluate.py +25 -0
- piloop-0.1.0/piloop/campaign/templates/project/piloop.toml +94 -0
- piloop-0.1.0/piloop/campaign/templates/titanic-tracks/.entire/.gitignore +5 -0
- piloop-0.1.0/piloop/campaign/templates/titanic-tracks/.entire/settings.json +1 -0
- piloop-0.1.0/piloop/campaign/templates/titanic-tracks/brief.md +33 -0
- piloop-0.1.0/piloop/campaign/templates/titanic-tracks/briefs/accuracy.md +4 -0
- piloop-0.1.0/piloop/campaign/templates/titanic-tracks/briefs/cost.md +5 -0
- piloop-0.1.0/piloop/campaign/templates/titanic-tracks/evaluate.py +89 -0
- piloop-0.1.0/piloop/campaign/templates/titanic-tracks/piloop.toml +41 -0
- piloop-0.1.0/piloop/campaign/templates/titanic-tracks/pyproject.toml +5 -0
- piloop-0.1.0/piloop/campaign/templates/titanic-tracks/solve.py +31 -0
- piloop-0.1.0/piloop/cli/__init__.py +1 -0
- piloop-0.1.0/piloop/cli/doctor.py +274 -0
- piloop-0.1.0/piloop/cli/main.py +995 -0
- piloop-0.1.0/piloop/cli/skills.py +85 -0
- piloop-0.1.0/piloop/cli/upgrade.py +31 -0
- piloop-0.1.0/piloop/cli/version.py +22 -0
- piloop-0.1.0/piloop/config.py +588 -0
- piloop-0.1.0/piloop/daemon/__init__.py +1 -0
- piloop-0.1.0/piloop/daemon/main.py +121 -0
- piloop-0.1.0/piloop/daemon/runner.py +732 -0
- piloop-0.1.0/piloop/daemon/scheduler.py +1300 -0
- piloop-0.1.0/piloop/daemon/serve.py +259 -0
- piloop-0.1.0/piloop/db/__init__.py +1 -0
- piloop-0.1.0/piloop/db/actor_triggers.sql +113 -0
- piloop-0.1.0/piloop/db/events.py +23 -0
- piloop-0.1.0/piloop/db/migrations/env.py +31 -0
- piloop-0.1.0/piloop/db/migrations/script.py.mako +24 -0
- piloop-0.1.0/piloop/db/migrations/versions/0001_initial.py +474 -0
- piloop-0.1.0/piloop/db/models.py +683 -0
- piloop-0.1.0/piloop/db/persistent_triggers.sql +70 -0
- piloop-0.1.0/piloop/db/session.py +140 -0
- piloop-0.1.0/piloop/db/sql.py +256 -0
- piloop-0.1.0/piloop/db/triggers/__init__.py +94 -0
- piloop-0.1.0/piloop/db/triggers/changelog.py +124 -0
- piloop-0.1.0/piloop/db/triggers/ddl.py +51 -0
- piloop-0.1.0/piloop/db/triggers/fts.py +66 -0
- piloop-0.1.0/piloop/db/triggers/links.py +22 -0
- piloop-0.1.0/piloop/db/triggers/provenance.py +51 -0
- piloop-0.1.0/piloop/deprecated.py +47 -0
- piloop-0.1.0/piloop/git.py +180 -0
- piloop-0.1.0/piloop/harnesses.py +234 -0
- piloop-0.1.0/piloop/mcp/__init__.py +173 -0
- piloop-0.1.0/piloop/mcp/claude.py +29 -0
- piloop-0.1.0/piloop/mcp/codex.py +110 -0
- piloop-0.1.0/piloop/mcp/pi.py +58 -0
- piloop-0.1.0/piloop/otel.py +109 -0
- piloop-0.1.0/piloop/proc.py +87 -0
- piloop-0.1.0/piloop/reports/__init__.py +1 -0
- piloop-0.1.0/piloop/reports/history.py +252 -0
- piloop-0.1.0/piloop/reports/overview.py +920 -0
- piloop-0.1.0/piloop/reports/pack.py +333 -0
- piloop-0.1.0/piloop/runtime/__init__.py +124 -0
- piloop-0.1.0/piloop/runtime/factory.py +48 -0
- piloop-0.1.0/piloop/runtime/herdr.py +775 -0
- piloop-0.1.0/piloop/runtime/subprocess.py +142 -0
- piloop-0.1.0/piloop/scoring/__init__.py +1 -0
- piloop-0.1.0/piloop/scoring/evaluate.py +151 -0
- piloop-0.1.0/piloop/scoring/ledger.py +496 -0
- piloop-0.1.0/piloop/scoring/verdict.py +160 -0
- piloop-0.1.0/piloop/settings.py +116 -0
- piloop-0.1.0/piloop/text.py +23 -0
- piloop-0.1.0/piloop/usage/__init__.py +180 -0
- piloop-0.1.0/piloop/usage/jsonl.py +276 -0
- piloop-0.1.0/piloop/usage/tallies/__init__.py +10 -0
- piloop-0.1.0/piloop/usage/tallies/claude.py +45 -0
- piloop-0.1.0/piloop/usage/tallies/codex.py +52 -0
- piloop-0.1.0/piloop/usage/tallies/pi.py +38 -0
- piloop-0.1.0/piloop/watch/__init__.py +1 -0
- piloop-0.1.0/piloop/watch/app.py +545 -0
- piloop-0.1.0/piloop/watch/panels.py +376 -0
- piloop-0.1.0/pyproject.toml +139 -0
- piloop-0.1.0/scripts/db_volume.py +363 -0
- piloop-0.1.0/scripts/gen_docs.py +366 -0
- piloop-0.1.0/scripts/screenshots.py +50 -0
- piloop-0.1.0/scripts/xai_search_mcp.py +178 -0
- piloop-0.1.0/skills/piloop-operate/SKILL.md +375 -0
- piloop-0.1.0/skills/piloop-review/SKILL.md +275 -0
- piloop-0.1.0/skills/piloop-setup/SKILL.md +222 -0
- piloop-0.1.0/tests/agents/test_capture.py +41 -0
- piloop-0.1.0/tests/agents/test_launcher.py +720 -0
- piloop-0.1.0/tests/agents/test_scout.py +278 -0
- piloop-0.1.0/tests/campaign/test_inbox.py +280 -0
- piloop-0.1.0/tests/campaign/test_project.py +206 -0
- piloop-0.1.0/tests/campaign/test_spend.py +157 -0
- piloop-0.1.0/tests/campaign/test_stop.py +404 -0
- piloop-0.1.0/tests/cli/test_cli.py +1164 -0
- piloop-0.1.0/tests/cli/test_doctor.py +273 -0
- piloop-0.1.0/tests/cli/test_skills.py +104 -0
- piloop-0.1.0/tests/cli/test_version.py +31 -0
- piloop-0.1.0/tests/conftest.py +349 -0
- piloop-0.1.0/tests/daemon/test_daemon.py +317 -0
- piloop-0.1.0/tests/daemon/test_research.py +214 -0
- piloop-0.1.0/tests/daemon/test_runner.py +1512 -0
- piloop-0.1.0/tests/daemon/test_scheduler.py +1767 -0
- piloop-0.1.0/tests/daemon/test_serve.py +330 -0
- piloop-0.1.0/tests/daemon/test_tracks_e2e.py +149 -0
- piloop-0.1.0/tests/daemon/test_triggers.py +720 -0
- piloop-0.1.0/tests/db/test_db_triggers.py +173 -0
- piloop-0.1.0/tests/db/test_fts.py +145 -0
- piloop-0.1.0/tests/db/test_migrations.py +180 -0
- piloop-0.1.0/tests/db/test_plans.py +103 -0
- piloop-0.1.0/tests/db/test_sql.py +388 -0
- piloop-0.1.0/tests/fixtures/__init__.py +0 -0
- piloop-0.1.0/tests/fixtures/fake_bin.py +26 -0
- piloop-0.1.0/tests/fixtures/fake_entire.py +93 -0
- piloop-0.1.0/tests/fixtures/fake_herdr.py +135 -0
- piloop-0.1.0/tests/fixtures/hold_lock.py +27 -0
- piloop-0.1.0/tests/fixtures/said/claude.jsonl +8 -0
- piloop-0.1.0/tests/fixtures/said/codex.jsonl +7 -0
- piloop-0.1.0/tests/fixtures/said/pi.jsonl +5 -0
- piloop-0.1.0/tests/fixtures/sessions/claude.jsonl +7 -0
- piloop-0.1.0/tests/fixtures/sessions/codex.jsonl +7 -0
- piloop-0.1.0/tests/fixtures/sessions/pi.jsonl +7 -0
- piloop-0.1.0/tests/mcp/test_mcp.py +333 -0
- piloop-0.1.0/tests/reports/test_history.py +251 -0
- piloop-0.1.0/tests/reports/test_overview.py +724 -0
- piloop-0.1.0/tests/reports/test_pack.py +230 -0
- piloop-0.1.0/tests/reports/test_tracks.py +130 -0
- piloop-0.1.0/tests/runtime/test_herdr.py +934 -0
- piloop-0.1.0/tests/runtime/test_subprocess.py +147 -0
- piloop-0.1.0/tests/scoring/test_contract.py +105 -0
- piloop-0.1.0/tests/scoring/test_evaluate.py +109 -0
- piloop-0.1.0/tests/scoring/test_verdict.py +258 -0
- piloop-0.1.0/tests/test_config.py +321 -0
- piloop-0.1.0/tests/test_deprecated.py +54 -0
- piloop-0.1.0/tests/test_git.py +45 -0
- piloop-0.1.0/tests/test_infra.py +103 -0
- piloop-0.1.0/tests/test_proc.py +16 -0
- piloop-0.1.0/tests/test_xai_search.py +118 -0
- piloop-0.1.0/tests/usage/test_usage.py +386 -0
- piloop-0.1.0/tests/watch/test_app.py +835 -0
- piloop-0.1.0/uv.lock +1269 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something in piloop does not work as the docs say.
|
|
3
|
+
labels: [bug]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: what
|
|
7
|
+
attributes:
|
|
8
|
+
label: What happened
|
|
9
|
+
description: What you did, what you expected, and what happened instead.
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: reproduce
|
|
14
|
+
attributes:
|
|
15
|
+
label: How to reproduce
|
|
16
|
+
description: The smallest set of steps or commands that shows the problem.
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: doctor
|
|
21
|
+
attributes:
|
|
22
|
+
label: Output of `piloop --version` and `piloop doctor`
|
|
23
|
+
render: text
|
|
24
|
+
validations:
|
|
25
|
+
required: true
|
|
26
|
+
- type: input
|
|
27
|
+
id: platform
|
|
28
|
+
attributes:
|
|
29
|
+
label: Operating system and harnesses
|
|
30
|
+
placeholder: macOS 26, Claude Code 2.1, runtime = "herdr"
|
|
31
|
+
validations:
|
|
32
|
+
required: true
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Propose a change or a new feature.
|
|
3
|
+
labels: [enhancement]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: The problem
|
|
9
|
+
description: What you are trying to do, and why piloop makes it hard today.
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: proposal
|
|
14
|
+
attributes:
|
|
15
|
+
label: Your proposal
|
|
16
|
+
description: What you want piloop to do. Include the commands or config you have in mind.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
<!-- What this changes and why. Link the issue it fixes. -->
|
|
4
|
+
|
|
5
|
+
## Test plan
|
|
6
|
+
|
|
7
|
+
<!-- How you verified it: the tests you added, and anything you ran by hand. -->
|
|
8
|
+
|
|
9
|
+
- [ ] `make` passes (format, lint, types, tests with 100% coverage, generated docs).
|
|
10
|
+
- [ ] A user-visible change has a line under `[Unreleased]` in CHANGELOG.md.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: uv
|
|
4
|
+
directory: /
|
|
5
|
+
schedule:
|
|
6
|
+
interval: weekly
|
|
7
|
+
cooldown:
|
|
8
|
+
default-days: 7
|
|
9
|
+
groups:
|
|
10
|
+
python:
|
|
11
|
+
patterns: ["*"]
|
|
12
|
+
- package-ecosystem: github-actions
|
|
13
|
+
directory: /
|
|
14
|
+
schedule:
|
|
15
|
+
interval: monthly
|
|
16
|
+
groups:
|
|
17
|
+
actions:
|
|
18
|
+
patterns: ["*"]
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request: {}
|
|
7
|
+
workflow_call: {}
|
|
8
|
+
|
|
9
|
+
env:
|
|
10
|
+
COLUMNS: 150
|
|
11
|
+
UV_FROZEN: "1"
|
|
12
|
+
UV_PYTHON_PREFERENCE: only-managed
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
concurrency:
|
|
18
|
+
group: ci-${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.run_id }}
|
|
19
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
lint:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v7
|
|
26
|
+
with:
|
|
27
|
+
persist-credentials: false
|
|
28
|
+
- uses: astral-sh/setup-uv@v7
|
|
29
|
+
with:
|
|
30
|
+
python-version: "3.14"
|
|
31
|
+
enable-cache: true
|
|
32
|
+
cache-suffix: lint
|
|
33
|
+
- run: uv sync
|
|
34
|
+
- uses: pre-commit/action@v3.0.1
|
|
35
|
+
with:
|
|
36
|
+
extra_args: --all-files --verbose
|
|
37
|
+
env:
|
|
38
|
+
SKIP: no-commit-to-branch
|
|
39
|
+
UV_NO_SYNC: "1"
|
|
40
|
+
|
|
41
|
+
test:
|
|
42
|
+
name: test on ${{ matrix.os }}
|
|
43
|
+
runs-on: ${{ matrix.os }}
|
|
44
|
+
timeout-minutes: 40
|
|
45
|
+
strategy:
|
|
46
|
+
fail-fast: false
|
|
47
|
+
matrix:
|
|
48
|
+
include:
|
|
49
|
+
- os: ubuntu-latest
|
|
50
|
+
make: testcov
|
|
51
|
+
# Coverage is measured on Linux: a few paths (the lock holder from /proc/locks) exist only there.
|
|
52
|
+
- os: macos-latest
|
|
53
|
+
make: test
|
|
54
|
+
steps:
|
|
55
|
+
- uses: actions/checkout@v7
|
|
56
|
+
with:
|
|
57
|
+
persist-credentials: false
|
|
58
|
+
- uses: astral-sh/setup-uv@v7
|
|
59
|
+
with:
|
|
60
|
+
python-version: "3.14"
|
|
61
|
+
enable-cache: true
|
|
62
|
+
cache-suffix: test
|
|
63
|
+
- run: uv sync
|
|
64
|
+
- run: make ${{ matrix.make }}
|
|
65
|
+
|
|
66
|
+
install:
|
|
67
|
+
name: install.sh quickstart
|
|
68
|
+
runs-on: ubuntu-latest
|
|
69
|
+
timeout-minutes: 15
|
|
70
|
+
steps:
|
|
71
|
+
- uses: actions/checkout@v7
|
|
72
|
+
with:
|
|
73
|
+
persist-credentials: false
|
|
74
|
+
- run: git config --global user.name piloop-ci && git config --global user.email ci@piloop
|
|
75
|
+
- run: PILOOP_SRC=. ./install.sh
|
|
76
|
+
- name: enwik8 example, headless (no Herdr on a runner)
|
|
77
|
+
env:
|
|
78
|
+
PILOOP_PROJECT_RUNTIME: subprocess
|
|
79
|
+
COLUMNS: 200
|
|
80
|
+
run: |
|
|
81
|
+
export PATH="$HOME/.local/bin:$PATH"
|
|
82
|
+
piloop init --example enwik8 /tmp/enwik8 | tee /tmp/init.txt
|
|
83
|
+
grep -q "registered; baseline candidate#1" /tmp/init.txt
|
|
84
|
+
piloop status enwik8
|
|
85
|
+
- name: the wheel carries the skills (a stand-in codex on PATH)
|
|
86
|
+
run: |
|
|
87
|
+
export PATH="$HOME/.local/bin:$PATH"
|
|
88
|
+
mkdir -p /tmp/bin && printf '#!/bin/sh\n' > /tmp/bin/codex && chmod +x /tmp/bin/codex
|
|
89
|
+
PATH="/tmp/bin:$PATH" piloop install-skills
|
|
90
|
+
test -f ~/.agents/skills/piloop-operate/SKILL.md
|
|
91
|
+
|
|
92
|
+
check:
|
|
93
|
+
if: always()
|
|
94
|
+
needs: [lint, test, install]
|
|
95
|
+
runs-on: ubuntu-latest
|
|
96
|
+
steps:
|
|
97
|
+
- uses: re-actors/alls-green@release/v1
|
|
98
|
+
with:
|
|
99
|
+
jobs: ${{ toJSON(needs) }}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
ci:
|
|
12
|
+
uses: ./.github/workflows/ci.yml
|
|
13
|
+
|
|
14
|
+
release:
|
|
15
|
+
needs: ci
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
permissions:
|
|
18
|
+
contents: write
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v7
|
|
21
|
+
with:
|
|
22
|
+
persist-credentials: false
|
|
23
|
+
- uses: astral-sh/setup-uv@v7
|
|
24
|
+
with:
|
|
25
|
+
python-version: "3.14"
|
|
26
|
+
- name: The tag matches the package version
|
|
27
|
+
run: test "v$(uv version --short)" = "$GITHUB_REF_NAME"
|
|
28
|
+
- run: uv build
|
|
29
|
+
- name: Release notes from CHANGELOG.md
|
|
30
|
+
run: |
|
|
31
|
+
version="${GITHUB_REF_NAME#v}"
|
|
32
|
+
awk -v v="$version" '$0 ~ "^## \\[" v "\\]" {on=1; next} on && /^## \[/ {exit} on' CHANGELOG.md > notes.md
|
|
33
|
+
test -s notes.md || { echo "CHANGELOG.md has no section for $version"; exit 1; }
|
|
34
|
+
- name: Create the GitHub release
|
|
35
|
+
env:
|
|
36
|
+
GH_TOKEN: ${{ github.token }}
|
|
37
|
+
run: gh release create "$GITHUB_REF_NAME" dist/* --title "$GITHUB_REF_NAME" --notes-file notes.md
|
|
38
|
+
- uses: actions/upload-artifact@v7
|
|
39
|
+
with:
|
|
40
|
+
name: dist
|
|
41
|
+
path: dist/
|
|
42
|
+
|
|
43
|
+
publish:
|
|
44
|
+
needs: release
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
# PyPI trusted publishing: pypi.org trusts this repo, this workflow and this environment. No token.
|
|
47
|
+
environment:
|
|
48
|
+
name: release
|
|
49
|
+
url: https://pypi.org/project/piloop/
|
|
50
|
+
permissions:
|
|
51
|
+
id-token: write
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/download-artifact@v8
|
|
54
|
+
with:
|
|
55
|
+
name: dist
|
|
56
|
+
path: dist/
|
|
57
|
+
- uses: astral-sh/setup-uv@v7
|
|
58
|
+
- run: uv publish --trusted-publishing always
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Keeps main identical in hiloopai/piloop and its private mirror hiloopai/piloop-dev, in both directions. Experimental
|
|
2
|
+
# branches live only in piloop-dev; merging one into its main publishes it. A diverged main fails here, never forces.
|
|
3
|
+
name: Sync main
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
workflow_dispatch: {}
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: sync-main
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
sync:
|
|
18
|
+
if: contains(fromJSON('["hiloopai/piloop", "hiloopai/piloop-dev"]'), github.repository)
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v7
|
|
22
|
+
with:
|
|
23
|
+
fetch-depth: 0
|
|
24
|
+
persist-credentials: false
|
|
25
|
+
- env:
|
|
26
|
+
DEPLOY_KEY: ${{ secrets.SYNC_DEPLOY_KEY }}
|
|
27
|
+
TARGET: ${{ github.repository == 'hiloopai/piloop' && 'hiloopai/piloop-dev' || 'hiloopai/piloop' }}
|
|
28
|
+
SSH_AUTH_SOCK: /tmp/ssh-agent.sock
|
|
29
|
+
run: |
|
|
30
|
+
ssh-agent -a "$SSH_AUTH_SOCK" > /dev/null
|
|
31
|
+
ssh-add - <<< "$DEPLOY_KEY"
|
|
32
|
+
mkdir -p ~/.ssh
|
|
33
|
+
ssh-keyscan github.com >> ~/.ssh/known_hosts
|
|
34
|
+
git push "git@github.com:$TARGET.git" HEAD:refs/heads/main
|
piloop-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
|
+
rev: v5.0.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: no-commit-to-branch
|
|
6
|
+
- id: check-yaml
|
|
7
|
+
- id: check-toml
|
|
8
|
+
- id: end-of-file-fixer
|
|
9
|
+
- id: trailing-whitespace
|
|
10
|
+
- id: check-added-large-files
|
|
11
|
+
args: [--maxkb=1024, --enforce-all]
|
|
12
|
+
exclude: ^uv\.lock$
|
|
13
|
+
|
|
14
|
+
- repo: local
|
|
15
|
+
hooks:
|
|
16
|
+
- id: format
|
|
17
|
+
name: Format
|
|
18
|
+
entry: make
|
|
19
|
+
args: [format]
|
|
20
|
+
language: system
|
|
21
|
+
types: [python]
|
|
22
|
+
pass_filenames: false
|
|
23
|
+
- id: lint
|
|
24
|
+
name: Lint
|
|
25
|
+
entry: make
|
|
26
|
+
args: [lint]
|
|
27
|
+
language: system
|
|
28
|
+
types: [python]
|
|
29
|
+
pass_filenames: false
|
|
30
|
+
- id: typecheck
|
|
31
|
+
name: Typecheck
|
|
32
|
+
entry: make
|
|
33
|
+
args: [typecheck]
|
|
34
|
+
language: system
|
|
35
|
+
types: [python]
|
|
36
|
+
pass_filenames: false
|
|
37
|
+
- id: docs
|
|
38
|
+
name: Generated docs
|
|
39
|
+
entry: make
|
|
40
|
+
args: [docs-check]
|
|
41
|
+
language: system
|
|
42
|
+
types: [python]
|
|
43
|
+
pass_filenames: false
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.14
|
piloop-0.1.0/AGENTS.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Operating piloop
|
|
2
|
+
|
|
3
|
+
This file is for a coding agent that a human asks to set up, run or review a piloop campaign. To change piloop's own
|
|
4
|
+
code, read [CONTRIBUTING.md](CONTRIBUTING.md) instead.
|
|
5
|
+
|
|
6
|
+
If `PILOOP_ACTOR` is already set to a `worker#`, `watchdog#`, `research#` or `scout#` id, piloop started you. Follow
|
|
7
|
+
your brief, and ignore this file and the skills.
|
|
8
|
+
|
|
9
|
+
piloop runs an autoresearch campaign on a git repo. A daemon starts coding agents (Claude Code, Codex or pi). Each
|
|
10
|
+
agent tries an idea in its own git worktree. piloop scores every commit with the project's evaluate command and keeps
|
|
11
|
+
what beats the head. You, the agent that the human talks to, set up the campaign and act as its orchestrator.
|
|
12
|
+
|
|
13
|
+
## The skills
|
|
14
|
+
|
|
15
|
+
Each task has an [Agent Skill](https://agentskills.io). Read the one that matches the task. Each `SKILL.md` is
|
|
16
|
+
complete on its own.
|
|
17
|
+
|
|
18
|
+
| Skill | Use it to |
|
|
19
|
+
|---|---|
|
|
20
|
+
| [piloop-setup](skills/piloop-setup/SKILL.md) | Set up or change a campaign in the current repo: check the machine, interview the human, write `brief.md` and `piloop.toml`, register the project, start the daemon. |
|
|
21
|
+
| [piloop-operate](skills/piloop-operate/SKILL.md) | Orchestrate a running campaign: the inbox loop, ideas and priorities, escalations and decisions, sweeps, steering workers. |
|
|
22
|
+
| [piloop-review](skills/piloop-review/SKILL.md) | Review a campaign during or after a run: are the gains real, did an agent game the evaluation, where did the time and tokens go. |
|
|
23
|
+
|
|
24
|
+
`piloop install-skills` copies these skills into `~/.claude/skills` (Claude Code) and `~/.agents/skills` (Codex, pi,
|
|
25
|
+
Gemini CLI, Cursor), for each of these harnesses on the `PATH`. The installer and `piloop upgrade` run it, so the
|
|
26
|
+
skills always match the installed CLI. `piloop doctor` reports a missing or old copy.
|
|
27
|
+
|
|
28
|
+
## The interface is the CLI
|
|
29
|
+
|
|
30
|
+
The database is the contract, and the `piloop` CLI is the only way in:
|
|
31
|
+
|
|
32
|
+
- `piloop sql "<one statement>"` reads and writes the database.
|
|
33
|
+
- `piloop schema` prints the conventions and every table. Read it before your first write.
|
|
34
|
+
- `piloop status` shows the state of each project.
|
|
35
|
+
- `piloop inbox` lists what waits for a decision.
|
|
36
|
+
- `piloop inbox wait` blocks until something needs you.
|
|
37
|
+
- `piloop --help` lists every other command.
|
|
38
|
+
|
|
39
|
+
## Rules
|
|
40
|
+
|
|
41
|
+
- Run every command as `PILOOP_ACTOR=orchestrator piloop …`. Your writes are then signed as yours, and
|
|
42
|
+
`piloop inbox wait` skips them.
|
|
43
|
+
- Record every decision that you make for the human as a `decision` comment with a priority. The human reviews and
|
|
44
|
+
revises these decisions in the inbox. You do not have to wait for the human.
|
|
45
|
+
|
|
46
|
+
## Documentation
|
|
47
|
+
|
|
48
|
+
The documentation is at [piloop.autoresearch.inc](https://piloop.autoresearch.inc). It is also in `docs/` in this repo.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to piloop are in this file. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and piloop follows
|
|
5
|
+
[Semantic Versioning](https://semver.org/spec/v2.0.0.html). Before 1.0, a minor release may contain breaking changes.
|
|
6
|
+
A deprecated configuration key shows a warning for at least one minor release before it is removed.
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2026-10-13
|
|
11
|
+
|
|
12
|
+
Initial public release.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- `piloop init`: makes a git repo a project, measures the baseline and registers it. Two bundled examples:
|
|
17
|
+
`enwik8` (compress Wikipedia text) and `titanic-tracks` (accuracy and CPU cost on Kaggle's Titanic data).
|
|
18
|
+
- The daemon, `piloop serve`: starts coding agents (Claude Code, Codex or pi) in git worktrees, scores every commit
|
|
19
|
+
with the project's evaluate command, and keeps what beats the head.
|
|
20
|
+
- The verdict: one primary metric that must improve with confidence, guardrail metrics with margins and floors, and
|
|
21
|
+
a paired bootstrap over per-unit results.
|
|
22
|
+
- Three agent roles: the worker, the watchdog and the research agent, with a scout mode for outside techniques.
|
|
23
|
+
- Ideas, seeds, links between ideas, branch runs from pinned starting points, notes on regressed results, and
|
|
24
|
+
imported reference candidates.
|
|
25
|
+
- Tracks: several objectives for one project, on one trunk.
|
|
26
|
+
- The orchestrator skills (setup, operate, review) for Claude Code, Codex, pi, Gemini CLI and Cursor, and the inbox
|
|
27
|
+
where the orchestrator records its decisions.
|
|
28
|
+
- `piloop watch`: the campaign on one screen, with keys to act on it.
|
|
29
|
+
- Stop conditions, token accounting for every agent, and a hard spend limit in USD.
|
|
30
|
+
- Session capture of every agent with Entire.
|
|
31
|
+
- MCP servers for the agents of a role, defined once for every harness, with keys from the daemon's environment or
|
|
32
|
+
`PILOOP_SECRETS_COMMAND`.
|
|
33
|
+
- `piloop restart`, `piloop upgrade`, `piloop doctor` and `piloop service-unit` for campaigns that run for days.
|
|
34
|
+
|
|
35
|
+
[Unreleased]: https://github.com/hiloopai/piloop/compare/v0.1.0...HEAD
|
|
36
|
+
[0.1.0]: https://github.com/hiloopai/piloop/releases/tag/v0.1.0
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Contributing to piloop
|
|
2
|
+
|
|
3
|
+
This file explains how to set up a development checkout, run the checks and send a change.
|
|
4
|
+
|
|
5
|
+
## Set up
|
|
6
|
+
|
|
7
|
+
You need git, [uv](https://docs.astral.sh/uv/) and `make`.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
git clone https://github.com/hiloopai/piloop
|
|
11
|
+
cd piloop
|
|
12
|
+
make install
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
`make install` installs the dependencies and the pre-commit hooks.
|
|
16
|
+
|
|
17
|
+
To try the installer from your checkout, as CI does:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
PILOOP_SRC=. ./install.sh
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Run the checks
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
make
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`make` formats the code, runs the linter (ruff), runs the type checker (ty), runs the tests with coverage, and
|
|
30
|
+
regenerates the generated files. Coverage must be 100%. The full test suite takes several minutes. While you work,
|
|
31
|
+
run only the tests that you need:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
COLUMNS=150 uv run pytest tests/scoring
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The tests marked `herdr` need a local [Herdr](https://herdr.dev). They are skipped when `herdr` is not on your
|
|
38
|
+
`PATH`.
|
|
39
|
+
|
|
40
|
+
Other targets: `make format`, `make lint`, `make typecheck`, `make test` (no coverage), `make testcov`, `make docs`
|
|
41
|
+
and `make docs-check`. CI runs the pre-commit hooks, `make testcov` on Linux, `make test` on macOS, and `install.sh`
|
|
42
|
+
with the enwik8 example.
|
|
43
|
+
|
|
44
|
+
## Generated files
|
|
45
|
+
|
|
46
|
+
`make docs` writes these files from the code. Never edit them by hand:
|
|
47
|
+
|
|
48
|
+
- `docs/reference/configuration.mdx`, from the models that `piloop.config.ProjectConfig` reaches (in
|
|
49
|
+
`piloop/config.py`, `piloop/harnesses.py`, `piloop/mcp/` and `piloop/usage/`), from `piloop/deprecated.py`, and from
|
|
50
|
+
the header in `scripts/gen_docs.py`.
|
|
51
|
+
- `docs/reference/schema.mdx`, from `piloop/db/models.py`.
|
|
52
|
+
- `piloop/db/actor_triggers.sql` and `piloop/db/persistent_triggers.sql`, from `piloop/db/triggers/`.
|
|
53
|
+
- The part between the markers of `docs/architecture/data-model.mdx`, `state-machines.mdx` and `code-layout.mdx`:
|
|
54
|
+
the diagram of the tables, the values of the state enums, and the graph of the imports between the subpackages.
|
|
55
|
+
|
|
56
|
+
`make docs-check` fails when one of them is stale. The pre-commit hook runs it.
|
|
57
|
+
|
|
58
|
+
## Documentation
|
|
59
|
+
|
|
60
|
+
The documentation site is in `docs/`. It is a [Mintlify](https://mintlify.com) site: `docs/docs.json` and one `.mdx`
|
|
61
|
+
file for each page. To preview it, with Node.js installed:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
cd docs
|
|
65
|
+
npx mint dev
|
|
66
|
+
npx mint broken-links --check-anchors
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
In `.mdx` files, `{`, `}`, `<` and `>` in text are syntax. Put them in code spans, or escape them.
|
|
70
|
+
|
|
71
|
+
## Change the database schema
|
|
72
|
+
|
|
73
|
+
1. Change the models in `piloop/db/models.py`.
|
|
74
|
+
2. Create a new Alembic revision:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
uv run alembic revision --autogenerate -m "add the foo column to ideas"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
3. Read the generated revision and fix what autogenerate missed.
|
|
81
|
+
4. Run `make docs`.
|
|
82
|
+
|
|
83
|
+
Never edit an existing revision. Users have databases at every revision, and piloop migrates them when it starts. A
|
|
84
|
+
batch migration that rebuilds a table drops its triggers, so call `piloop.db.triggers.recreate` after it.
|
|
85
|
+
|
|
86
|
+
## Deprecate a configuration key
|
|
87
|
+
|
|
88
|
+
To rename or remove a key of `piloop.toml`, add a bridge in `piloop/deprecated.py`. The module docstring explains
|
|
89
|
+
how. The old key then keeps working, with a warning, for at least one minor release. Add a line under `Deprecated` in
|
|
90
|
+
`CHANGELOG.md`.
|
|
91
|
+
|
|
92
|
+
## Code style
|
|
93
|
+
|
|
94
|
+
- Python 3.14, single quotes, lines of at most 120 characters, Google-style docstrings.
|
|
95
|
+
- No new `Any` (the existing uses type untyped JSON), no `# type: ignore`, no new `noqa`. Fix the cause instead.
|
|
96
|
+
- No `logging`. Emit spans and span events with `piloop.otel`.
|
|
97
|
+
- Comments explain a reason that is not obvious, a gotcha or a TODO. They do not repeat the code.
|
|
98
|
+
|
|
99
|
+
## Package layout
|
|
100
|
+
|
|
101
|
+
The package has one subpackage for each concern. Imports only point down this list:
|
|
102
|
+
|
|
103
|
+
1. `db/`: storage, the SQL gate for agents, the events feed.
|
|
104
|
+
2. `mcp/`, `usage/`, and `config.py` with `harnesses.py`: MCP servers, token usage, the project configuration.
|
|
105
|
+
3. `runtime/`: where the agent processes run (a background process, or a Herdr pane).
|
|
106
|
+
4. `scoring/`: the evaluate command, the ledger, the verdict.
|
|
107
|
+
5. `agents/`: the roles and their prompts, the agent lifecycle, session capture.
|
|
108
|
+
6. `campaign/`: projects, ideas, the inbox, stop conditions, the spend limit.
|
|
109
|
+
7. `reports/`: status, history, the research pack.
|
|
110
|
+
8. `daemon/`: the process, the scheduler, the run executor.
|
|
111
|
+
9. `watch/` and `cli/`.
|
|
112
|
+
|
|
113
|
+
The top-level modules `settings`, `otel`, `git`, `proc`, `text` and `deprecated` are leaves that every subpackage may
|
|
114
|
+
use.
|
|
115
|
+
|
|
116
|
+
## Send a change
|
|
117
|
+
|
|
118
|
+
- Open an issue first for a large change, so that we can agree on the approach.
|
|
119
|
+
- Use [Conventional Commits](https://www.conventionalcommits.org/): `fix: keep the head when a merge conflicts`,
|
|
120
|
+
`feat(watch): filter the agents panel`.
|
|
121
|
+
- Add a line under `[Unreleased]` in [CHANGELOG.md](CHANGELOG.md) for every change that a user can see.
|
|
122
|
+
- Make sure that `make` passes before you open the pull request.
|
|
123
|
+
|
|
124
|
+
## Release
|
|
125
|
+
|
|
126
|
+
Maintainers only.
|
|
127
|
+
|
|
128
|
+
1. Set `version` in `pyproject.toml`, and run `uv lock`.
|
|
129
|
+
2. In `CHANGELOG.md`, rename `[Unreleased]` to the version and the date, add a new empty `[Unreleased]`, and update the
|
|
130
|
+
links at the bottom.
|
|
131
|
+
3. Merge that change, then tag the commit on `main`: `git tag v0.2.0 && git push origin v0.2.0`.
|
|
132
|
+
|
|
133
|
+
The `Release` workflow runs CI, checks that the tag matches the version, creates the GitHub release with the
|
|
134
|
+
changelog section as its notes, and publishes the package to PyPI.
|
piloop-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Autoresearch, Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
piloop-0.1.0/Makefile
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
.DEFAULT_GOAL := all
|
|
2
|
+
|
|
3
|
+
.PHONY: install
|
|
4
|
+
install: ## Install deps and pre-commit hooks
|
|
5
|
+
uv sync --frozen
|
|
6
|
+
uv run pre-commit install --install-hooks
|
|
7
|
+
|
|
8
|
+
.PHONY: format
|
|
9
|
+
format: ## Format the code
|
|
10
|
+
uv run ruff format
|
|
11
|
+
uv run ruff check --fix --fix-only
|
|
12
|
+
|
|
13
|
+
.PHONY: lint
|
|
14
|
+
lint: ## Lint the code
|
|
15
|
+
uv run ruff format --check
|
|
16
|
+
uv run ruff check
|
|
17
|
+
|
|
18
|
+
.PHONY: typecheck
|
|
19
|
+
typecheck: ## Static type check
|
|
20
|
+
uv run ty check
|
|
21
|
+
|
|
22
|
+
.PHONY: test
|
|
23
|
+
test: ## Run tests (no coverage)
|
|
24
|
+
COLUMNS=150 uv run pytest --durations=10
|
|
25
|
+
|
|
26
|
+
.PHONY: testcov
|
|
27
|
+
testcov: ## Run tests with coverage; fails under 100%
|
|
28
|
+
COLUMNS=150 uv run coverage run -m pytest --durations=10
|
|
29
|
+
uv run coverage report
|
|
30
|
+
|
|
31
|
+
.PHONY: docs
|
|
32
|
+
docs: ## Regenerate the configuration and schema reference pages and the trigger SQL from code
|
|
33
|
+
uv run python scripts/gen_docs.py
|
|
34
|
+
|
|
35
|
+
.PHONY: docs-check
|
|
36
|
+
docs-check: ## Fail if a generated file is stale
|
|
37
|
+
uv run python scripts/gen_docs.py --check
|
|
38
|
+
|
|
39
|
+
.PHONY: all
|
|
40
|
+
all: format lint typecheck testcov docs
|