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.
Files changed (217) hide show
  1. piloop-0.1.0/.github/ISSUE_TEMPLATE/1_bug_report.yml +32 -0
  2. piloop-0.1.0/.github/ISSUE_TEMPLATE/2_feature_request.yml +16 -0
  3. piloop-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
  4. piloop-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +10 -0
  5. piloop-0.1.0/.github/dependabot.yml +18 -0
  6. piloop-0.1.0/.github/workflows/ci.yml +99 -0
  7. piloop-0.1.0/.github/workflows/release.yml +58 -0
  8. piloop-0.1.0/.github/workflows/sync.yml +34 -0
  9. piloop-0.1.0/.gitignore +13 -0
  10. piloop-0.1.0/.pre-commit-config.yaml +43 -0
  11. piloop-0.1.0/.python-version +1 -0
  12. piloop-0.1.0/AGENTS.md +48 -0
  13. piloop-0.1.0/CHANGELOG.md +36 -0
  14. piloop-0.1.0/CONTRIBUTING.md +134 -0
  15. piloop-0.1.0/LICENSE +21 -0
  16. piloop-0.1.0/Makefile +40 -0
  17. piloop-0.1.0/PKG-INFO +147 -0
  18. piloop-0.1.0/README.md +111 -0
  19. piloop-0.1.0/alembic.ini +5 -0
  20. piloop-0.1.0/docs/architecture/code-layout.mdx +82 -0
  21. piloop-0.1.0/docs/architecture/data-model.mdx +190 -0
  22. piloop-0.1.0/docs/architecture/extension-points.mdx +66 -0
  23. piloop-0.1.0/docs/architecture/overview.mdx +124 -0
  24. piloop-0.1.0/docs/architecture/run-lifecycle.mdx +82 -0
  25. piloop-0.1.0/docs/architecture/state-machines.mdx +94 -0
  26. piloop-0.1.0/docs/by-hand.mdx +192 -0
  27. piloop-0.1.0/docs/concepts/cost.mdx +79 -0
  28. piloop-0.1.0/docs/concepts/ideas-and-runs.mdx +114 -0
  29. piloop-0.1.0/docs/concepts/orchestrator.mdx +112 -0
  30. piloop-0.1.0/docs/concepts/projects.mdx +106 -0
  31. piloop-0.1.0/docs/concepts/roles.mdx +141 -0
  32. piloop-0.1.0/docs/concepts/session-capture.mdx +64 -0
  33. piloop-0.1.0/docs/concepts/tracks.mdx +76 -0
  34. piloop-0.1.0/docs/concepts/verdict.mdx +118 -0
  35. piloop-0.1.0/docs/docs.json +77 -0
  36. piloop-0.1.0/docs/favicon.svg +5 -0
  37. piloop-0.1.0/docs/guides/mcp-servers.mdx +92 -0
  38. piloop-0.1.0/docs/guides/reviewing.mdx +73 -0
  39. piloop-0.1.0/docs/guides/running-for-days.mdx +91 -0
  40. piloop-0.1.0/docs/guides/secrets.mdx +64 -0
  41. piloop-0.1.0/docs/guides/upgrading.mdx +81 -0
  42. piloop-0.1.0/docs/guides/watch.mdx +83 -0
  43. piloop-0.1.0/docs/images/watch-campaign.svg +249 -0
  44. piloop-0.1.0/docs/images/watch-candidates.svg +248 -0
  45. piloop-0.1.0/docs/images/watch-ideas.svg +249 -0
  46. piloop-0.1.0/docs/index.mdx +126 -0
  47. piloop-0.1.0/docs/quickstart.mdx +146 -0
  48. piloop-0.1.0/docs/reference/cli.mdx +285 -0
  49. piloop-0.1.0/docs/reference/configuration.mdx +233 -0
  50. piloop-0.1.0/docs/reference/environment.mdx +47 -0
  51. piloop-0.1.0/docs/reference/schema.mdx +233 -0
  52. piloop-0.1.0/docs/several-campaigns.mdx +58 -0
  53. piloop-0.1.0/install.sh +44 -0
  54. piloop-0.1.0/piloop/__init__.py +0 -0
  55. piloop-0.1.0/piloop/__main__.py +3 -0
  56. piloop-0.1.0/piloop/agents/__init__.py +1 -0
  57. piloop-0.1.0/piloop/agents/capture.py +118 -0
  58. piloop-0.1.0/piloop/agents/launcher.py +443 -0
  59. piloop-0.1.0/piloop/agents/prompts/research.md +229 -0
  60. piloop-0.1.0/piloop/agents/prompts/research_scout.md +129 -0
  61. piloop-0.1.0/piloop/agents/prompts/sql_procedures.md +295 -0
  62. piloop-0.1.0/piloop/agents/prompts/watchdog.md +30 -0
  63. piloop-0.1.0/piloop/agents/prompts/watchdog_incident.md +23 -0
  64. piloop-0.1.0/piloop/agents/prompts/watchdog_progress.md +25 -0
  65. piloop-0.1.0/piloop/agents/prompts/worker.md +94 -0
  66. piloop-0.1.0/piloop/agents/refill.py +33 -0
  67. piloop-0.1.0/piloop/agents/roles.py +214 -0
  68. piloop-0.1.0/piloop/agents/scout.py +159 -0
  69. piloop-0.1.0/piloop/campaign/__init__.py +1 -0
  70. piloop-0.1.0/piloop/campaign/ideas.py +347 -0
  71. piloop-0.1.0/piloop/campaign/inbox.py +235 -0
  72. piloop-0.1.0/piloop/campaign/project.py +242 -0
  73. piloop-0.1.0/piloop/campaign/spend.py +143 -0
  74. piloop-0.1.0/piloop/campaign/stop.py +147 -0
  75. piloop-0.1.0/piloop/campaign/templates/enwik8/.entire/.gitignore +5 -0
  76. piloop-0.1.0/piloop/campaign/templates/enwik8/.entire/settings.json +1 -0
  77. piloop-0.1.0/piloop/campaign/templates/enwik8/brief.md +32 -0
  78. piloop-0.1.0/piloop/campaign/templates/enwik8/compressor.py +13 -0
  79. piloop-0.1.0/piloop/campaign/templates/enwik8/evaluate.py +69 -0
  80. piloop-0.1.0/piloop/campaign/templates/enwik8/piloop.toml +31 -0
  81. piloop-0.1.0/piloop/campaign/templates/enwik8/pyproject.toml +5 -0
  82. piloop-0.1.0/piloop/campaign/templates/project/.entire/.gitignore +5 -0
  83. piloop-0.1.0/piloop/campaign/templates/project/.entire/settings.json +1 -0
  84. piloop-0.1.0/piloop/campaign/templates/project/brief.md +47 -0
  85. piloop-0.1.0/piloop/campaign/templates/project/evaluate.py +25 -0
  86. piloop-0.1.0/piloop/campaign/templates/project/piloop.toml +94 -0
  87. piloop-0.1.0/piloop/campaign/templates/titanic-tracks/.entire/.gitignore +5 -0
  88. piloop-0.1.0/piloop/campaign/templates/titanic-tracks/.entire/settings.json +1 -0
  89. piloop-0.1.0/piloop/campaign/templates/titanic-tracks/brief.md +33 -0
  90. piloop-0.1.0/piloop/campaign/templates/titanic-tracks/briefs/accuracy.md +4 -0
  91. piloop-0.1.0/piloop/campaign/templates/titanic-tracks/briefs/cost.md +5 -0
  92. piloop-0.1.0/piloop/campaign/templates/titanic-tracks/evaluate.py +89 -0
  93. piloop-0.1.0/piloop/campaign/templates/titanic-tracks/piloop.toml +41 -0
  94. piloop-0.1.0/piloop/campaign/templates/titanic-tracks/pyproject.toml +5 -0
  95. piloop-0.1.0/piloop/campaign/templates/titanic-tracks/solve.py +31 -0
  96. piloop-0.1.0/piloop/cli/__init__.py +1 -0
  97. piloop-0.1.0/piloop/cli/doctor.py +274 -0
  98. piloop-0.1.0/piloop/cli/main.py +995 -0
  99. piloop-0.1.0/piloop/cli/skills.py +85 -0
  100. piloop-0.1.0/piloop/cli/upgrade.py +31 -0
  101. piloop-0.1.0/piloop/cli/version.py +22 -0
  102. piloop-0.1.0/piloop/config.py +588 -0
  103. piloop-0.1.0/piloop/daemon/__init__.py +1 -0
  104. piloop-0.1.0/piloop/daemon/main.py +121 -0
  105. piloop-0.1.0/piloop/daemon/runner.py +732 -0
  106. piloop-0.1.0/piloop/daemon/scheduler.py +1300 -0
  107. piloop-0.1.0/piloop/daemon/serve.py +259 -0
  108. piloop-0.1.0/piloop/db/__init__.py +1 -0
  109. piloop-0.1.0/piloop/db/actor_triggers.sql +113 -0
  110. piloop-0.1.0/piloop/db/events.py +23 -0
  111. piloop-0.1.0/piloop/db/migrations/env.py +31 -0
  112. piloop-0.1.0/piloop/db/migrations/script.py.mako +24 -0
  113. piloop-0.1.0/piloop/db/migrations/versions/0001_initial.py +474 -0
  114. piloop-0.1.0/piloop/db/models.py +683 -0
  115. piloop-0.1.0/piloop/db/persistent_triggers.sql +70 -0
  116. piloop-0.1.0/piloop/db/session.py +140 -0
  117. piloop-0.1.0/piloop/db/sql.py +256 -0
  118. piloop-0.1.0/piloop/db/triggers/__init__.py +94 -0
  119. piloop-0.1.0/piloop/db/triggers/changelog.py +124 -0
  120. piloop-0.1.0/piloop/db/triggers/ddl.py +51 -0
  121. piloop-0.1.0/piloop/db/triggers/fts.py +66 -0
  122. piloop-0.1.0/piloop/db/triggers/links.py +22 -0
  123. piloop-0.1.0/piloop/db/triggers/provenance.py +51 -0
  124. piloop-0.1.0/piloop/deprecated.py +47 -0
  125. piloop-0.1.0/piloop/git.py +180 -0
  126. piloop-0.1.0/piloop/harnesses.py +234 -0
  127. piloop-0.1.0/piloop/mcp/__init__.py +173 -0
  128. piloop-0.1.0/piloop/mcp/claude.py +29 -0
  129. piloop-0.1.0/piloop/mcp/codex.py +110 -0
  130. piloop-0.1.0/piloop/mcp/pi.py +58 -0
  131. piloop-0.1.0/piloop/otel.py +109 -0
  132. piloop-0.1.0/piloop/proc.py +87 -0
  133. piloop-0.1.0/piloop/reports/__init__.py +1 -0
  134. piloop-0.1.0/piloop/reports/history.py +252 -0
  135. piloop-0.1.0/piloop/reports/overview.py +920 -0
  136. piloop-0.1.0/piloop/reports/pack.py +333 -0
  137. piloop-0.1.0/piloop/runtime/__init__.py +124 -0
  138. piloop-0.1.0/piloop/runtime/factory.py +48 -0
  139. piloop-0.1.0/piloop/runtime/herdr.py +775 -0
  140. piloop-0.1.0/piloop/runtime/subprocess.py +142 -0
  141. piloop-0.1.0/piloop/scoring/__init__.py +1 -0
  142. piloop-0.1.0/piloop/scoring/evaluate.py +151 -0
  143. piloop-0.1.0/piloop/scoring/ledger.py +496 -0
  144. piloop-0.1.0/piloop/scoring/verdict.py +160 -0
  145. piloop-0.1.0/piloop/settings.py +116 -0
  146. piloop-0.1.0/piloop/text.py +23 -0
  147. piloop-0.1.0/piloop/usage/__init__.py +180 -0
  148. piloop-0.1.0/piloop/usage/jsonl.py +276 -0
  149. piloop-0.1.0/piloop/usage/tallies/__init__.py +10 -0
  150. piloop-0.1.0/piloop/usage/tallies/claude.py +45 -0
  151. piloop-0.1.0/piloop/usage/tallies/codex.py +52 -0
  152. piloop-0.1.0/piloop/usage/tallies/pi.py +38 -0
  153. piloop-0.1.0/piloop/watch/__init__.py +1 -0
  154. piloop-0.1.0/piloop/watch/app.py +545 -0
  155. piloop-0.1.0/piloop/watch/panels.py +376 -0
  156. piloop-0.1.0/pyproject.toml +139 -0
  157. piloop-0.1.0/scripts/db_volume.py +363 -0
  158. piloop-0.1.0/scripts/gen_docs.py +366 -0
  159. piloop-0.1.0/scripts/screenshots.py +50 -0
  160. piloop-0.1.0/scripts/xai_search_mcp.py +178 -0
  161. piloop-0.1.0/skills/piloop-operate/SKILL.md +375 -0
  162. piloop-0.1.0/skills/piloop-review/SKILL.md +275 -0
  163. piloop-0.1.0/skills/piloop-setup/SKILL.md +222 -0
  164. piloop-0.1.0/tests/agents/test_capture.py +41 -0
  165. piloop-0.1.0/tests/agents/test_launcher.py +720 -0
  166. piloop-0.1.0/tests/agents/test_scout.py +278 -0
  167. piloop-0.1.0/tests/campaign/test_inbox.py +280 -0
  168. piloop-0.1.0/tests/campaign/test_project.py +206 -0
  169. piloop-0.1.0/tests/campaign/test_spend.py +157 -0
  170. piloop-0.1.0/tests/campaign/test_stop.py +404 -0
  171. piloop-0.1.0/tests/cli/test_cli.py +1164 -0
  172. piloop-0.1.0/tests/cli/test_doctor.py +273 -0
  173. piloop-0.1.0/tests/cli/test_skills.py +104 -0
  174. piloop-0.1.0/tests/cli/test_version.py +31 -0
  175. piloop-0.1.0/tests/conftest.py +349 -0
  176. piloop-0.1.0/tests/daemon/test_daemon.py +317 -0
  177. piloop-0.1.0/tests/daemon/test_research.py +214 -0
  178. piloop-0.1.0/tests/daemon/test_runner.py +1512 -0
  179. piloop-0.1.0/tests/daemon/test_scheduler.py +1767 -0
  180. piloop-0.1.0/tests/daemon/test_serve.py +330 -0
  181. piloop-0.1.0/tests/daemon/test_tracks_e2e.py +149 -0
  182. piloop-0.1.0/tests/daemon/test_triggers.py +720 -0
  183. piloop-0.1.0/tests/db/test_db_triggers.py +173 -0
  184. piloop-0.1.0/tests/db/test_fts.py +145 -0
  185. piloop-0.1.0/tests/db/test_migrations.py +180 -0
  186. piloop-0.1.0/tests/db/test_plans.py +103 -0
  187. piloop-0.1.0/tests/db/test_sql.py +388 -0
  188. piloop-0.1.0/tests/fixtures/__init__.py +0 -0
  189. piloop-0.1.0/tests/fixtures/fake_bin.py +26 -0
  190. piloop-0.1.0/tests/fixtures/fake_entire.py +93 -0
  191. piloop-0.1.0/tests/fixtures/fake_herdr.py +135 -0
  192. piloop-0.1.0/tests/fixtures/hold_lock.py +27 -0
  193. piloop-0.1.0/tests/fixtures/said/claude.jsonl +8 -0
  194. piloop-0.1.0/tests/fixtures/said/codex.jsonl +7 -0
  195. piloop-0.1.0/tests/fixtures/said/pi.jsonl +5 -0
  196. piloop-0.1.0/tests/fixtures/sessions/claude.jsonl +7 -0
  197. piloop-0.1.0/tests/fixtures/sessions/codex.jsonl +7 -0
  198. piloop-0.1.0/tests/fixtures/sessions/pi.jsonl +7 -0
  199. piloop-0.1.0/tests/mcp/test_mcp.py +333 -0
  200. piloop-0.1.0/tests/reports/test_history.py +251 -0
  201. piloop-0.1.0/tests/reports/test_overview.py +724 -0
  202. piloop-0.1.0/tests/reports/test_pack.py +230 -0
  203. piloop-0.1.0/tests/reports/test_tracks.py +130 -0
  204. piloop-0.1.0/tests/runtime/test_herdr.py +934 -0
  205. piloop-0.1.0/tests/runtime/test_subprocess.py +147 -0
  206. piloop-0.1.0/tests/scoring/test_contract.py +105 -0
  207. piloop-0.1.0/tests/scoring/test_evaluate.py +109 -0
  208. piloop-0.1.0/tests/scoring/test_verdict.py +258 -0
  209. piloop-0.1.0/tests/test_config.py +321 -0
  210. piloop-0.1.0/tests/test_deprecated.py +54 -0
  211. piloop-0.1.0/tests/test_git.py +45 -0
  212. piloop-0.1.0/tests/test_infra.py +103 -0
  213. piloop-0.1.0/tests/test_proc.py +16 -0
  214. piloop-0.1.0/tests/test_xai_search.py +118 -0
  215. piloop-0.1.0/tests/usage/test_usage.py +386 -0
  216. piloop-0.1.0/tests/watch/test_app.py +835 -0
  217. 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,5 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Documentation
4
+ url: https://piloop.autoresearch.inc
5
+ about: Install, quickstart, concepts and reference.
@@ -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
@@ -0,0 +1,13 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ .ruff_cache/
5
+ .coverage/
6
+ htmlcov/
7
+ dist/
8
+ node_modules/
9
+ piloop/templates/*/data/
10
+ .alembic-scratch.db*
11
+ *.db
12
+ *.db-wal
13
+ *.db-shm
@@ -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