piloop 0.2.0__tar.gz → 0.2.1__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 (408) hide show
  1. {piloop-0.2.0 → piloop-0.2.1}/CHANGELOG.md +10 -0
  2. {piloop-0.2.0 → piloop-0.2.1}/PKG-INFO +1 -1
  3. {piloop-0.2.0 → piloop-0.2.1}/piloop/plugins/host.py +9 -3
  4. {piloop-0.2.0 → piloop-0.2.1}/pyproject.toml +1 -1
  5. {piloop-0.2.0 → piloop-0.2.1}/tests/daemon/test_scheduler.py +21 -0
  6. {piloop-0.2.0 → piloop-0.2.1}/tests/test_plugins.py +1 -0
  7. {piloop-0.2.0 → piloop-0.2.1}/uv.lock +1 -1
  8. {piloop-0.2.0 → piloop-0.2.1}/.github/ISSUE_TEMPLATE/1_bug_report.yml +0 -0
  9. {piloop-0.2.0 → piloop-0.2.1}/.github/ISSUE_TEMPLATE/2_feature_request.yml +0 -0
  10. {piloop-0.2.0 → piloop-0.2.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  11. {piloop-0.2.0 → piloop-0.2.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  12. {piloop-0.2.0 → piloop-0.2.1}/.github/dependabot.yml +0 -0
  13. {piloop-0.2.0 → piloop-0.2.1}/.github/workflows/ci.yml +0 -0
  14. {piloop-0.2.0 → piloop-0.2.1}/.github/workflows/pr-title.yml +0 -0
  15. {piloop-0.2.0 → piloop-0.2.1}/.github/workflows/release.yml +0 -0
  16. {piloop-0.2.0 → piloop-0.2.1}/.github/workflows/sync.yml +0 -0
  17. {piloop-0.2.0 → piloop-0.2.1}/.gitignore +0 -0
  18. {piloop-0.2.0 → piloop-0.2.1}/.greptile/config.json +0 -0
  19. {piloop-0.2.0 → piloop-0.2.1}/.greptile/files.json +0 -0
  20. {piloop-0.2.0 → piloop-0.2.1}/.pre-commit-config.yaml +0 -0
  21. {piloop-0.2.0 → piloop-0.2.1}/.python-version +0 -0
  22. {piloop-0.2.0 → piloop-0.2.1}/AGENTS.md +0 -0
  23. {piloop-0.2.0 → piloop-0.2.1}/CONTRIBUTING.md +0 -0
  24. {piloop-0.2.0 → piloop-0.2.1}/LICENSE +0 -0
  25. {piloop-0.2.0 → piloop-0.2.1}/Makefile +0 -0
  26. {piloop-0.2.0 → piloop-0.2.1}/README.md +0 -0
  27. {piloop-0.2.0 → piloop-0.2.1}/alembic.ini +0 -0
  28. {piloop-0.2.0 → piloop-0.2.1}/cliff.toml +0 -0
  29. {piloop-0.2.0 → piloop-0.2.1}/docs/architecture/code-layout.mdx +0 -0
  30. {piloop-0.2.0 → piloop-0.2.1}/docs/architecture/data-model.mdx +0 -0
  31. {piloop-0.2.0 → piloop-0.2.1}/docs/architecture/extension-points.mdx +0 -0
  32. {piloop-0.2.0 → piloop-0.2.1}/docs/architecture/overview.mdx +0 -0
  33. {piloop-0.2.0 → piloop-0.2.1}/docs/architecture/run-lifecycle.mdx +0 -0
  34. {piloop-0.2.0 → piloop-0.2.1}/docs/architecture/state-machines.mdx +0 -0
  35. {piloop-0.2.0 → piloop-0.2.1}/docs/by-hand.mdx +0 -0
  36. {piloop-0.2.0 → piloop-0.2.1}/docs/concepts/artifact-store.mdx +0 -0
  37. {piloop-0.2.0 → piloop-0.2.1}/docs/concepts/campaigns.mdx +0 -0
  38. {piloop-0.2.0 → piloop-0.2.1}/docs/concepts/cost.mdx +0 -0
  39. {piloop-0.2.0 → piloop-0.2.1}/docs/concepts/ideas-and-runs.mdx +0 -0
  40. {piloop-0.2.0 → piloop-0.2.1}/docs/concepts/orchestrator.mdx +0 -0
  41. {piloop-0.2.0 → piloop-0.2.1}/docs/concepts/research-memory.mdx +0 -0
  42. {piloop-0.2.0 → piloop-0.2.1}/docs/concepts/roles.mdx +0 -0
  43. {piloop-0.2.0 → piloop-0.2.1}/docs/concepts/runtimes.mdx +0 -0
  44. {piloop-0.2.0 → piloop-0.2.1}/docs/concepts/session-capture.mdx +0 -0
  45. {piloop-0.2.0 → piloop-0.2.1}/docs/concepts/tracks.mdx +0 -0
  46. {piloop-0.2.0 → piloop-0.2.1}/docs/concepts/verdict.mdx +0 -0
  47. {piloop-0.2.0 → piloop-0.2.1}/docs/docs.json +0 -0
  48. {piloop-0.2.0 → piloop-0.2.1}/docs/favicon.svg +0 -0
  49. {piloop-0.2.0 → piloop-0.2.1}/docs/guides/mcp-servers.mdx +0 -0
  50. {piloop-0.2.0 → piloop-0.2.1}/docs/guides/reviewing.mdx +0 -0
  51. {piloop-0.2.0 → piloop-0.2.1}/docs/guides/running-for-days.mdx +0 -0
  52. {piloop-0.2.0 → piloop-0.2.1}/docs/guides/secrets.mdx +0 -0
  53. {piloop-0.2.0 → piloop-0.2.1}/docs/guides/upgrading.mdx +0 -0
  54. {piloop-0.2.0 → piloop-0.2.1}/docs/guides/watch.mdx +0 -0
  55. {piloop-0.2.0 → piloop-0.2.1}/docs/images/watch-campaign.svg +0 -0
  56. {piloop-0.2.0 → piloop-0.2.1}/docs/images/watch-candidates.svg +0 -0
  57. {piloop-0.2.0 → piloop-0.2.1}/docs/images/watch-ideas.svg +0 -0
  58. {piloop-0.2.0 → piloop-0.2.1}/docs/index.mdx +0 -0
  59. {piloop-0.2.0 → piloop-0.2.1}/docs/quickstart.mdx +0 -0
  60. {piloop-0.2.0 → piloop-0.2.1}/docs/reference/cli.mdx +0 -0
  61. {piloop-0.2.0 → piloop-0.2.1}/docs/reference/configuration.mdx +0 -0
  62. {piloop-0.2.0 → piloop-0.2.1}/docs/reference/environment.mdx +0 -0
  63. {piloop-0.2.0 → piloop-0.2.1}/docs/reference/event-feed.mdx +0 -0
  64. {piloop-0.2.0 → piloop-0.2.1}/docs/reference/schema.mdx +0 -0
  65. {piloop-0.2.0 → piloop-0.2.1}/docs/several-campaigns.mdx +0 -0
  66. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/capabilities.mdx +0 -0
  67. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/cwd-encoders.mdx +0 -0
  68. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/data-model.mdx +0 -0
  69. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/evaluate-examples.mdx +0 -0
  70. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/example-dir-store.mdx +0 -0
  71. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/example-min-gain.mdx +0 -0
  72. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/example-nice-runtime.mdx +0 -0
  73. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/example-no-unit-regression.mdx +0 -0
  74. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/example-stop-after-keeps.mdx +0 -0
  75. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/example-verdict-checks.mdx +0 -0
  76. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/harnesses.mdx +0 -0
  77. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/herdr-settings.mdx +0 -0
  78. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/imports.mdx +0 -0
  79. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/mcp-keys.mdx +0 -0
  80. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/queue-keys.mdx +0 -0
  81. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/readers.mdx +0 -0
  82. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/renderers.mdx +0 -0
  83. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/role-defaults.mdx +0 -0
  84. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/role-keys.mdx +0 -0
  85. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/roles.mdx +0 -0
  86. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/run-role-keys.mdx +0 -0
  87. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/runtime-protocol.mdx +0 -0
  88. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/runtimes.mdx +0 -0
  89. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/settings.mdx +0 -0
  90. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/states.mdx +0 -0
  91. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/stop.mdx +0 -0
  92. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/storage-backends.mdx +0 -0
  93. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/sweep-role-keys.mdx +0 -0
  94. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/tallies.mdx +0 -0
  95. {piloop-0.2.0 → piloop-0.2.1}/docs/snippets/generated/triggers.mdx +0 -0
  96. {piloop-0.2.0 → piloop-0.2.1}/examples/plugins/dir-store/README.md +0 -0
  97. {piloop-0.2.0 → piloop-0.2.1}/examples/plugins/dir-store/piloop_dir_store/__init__.py +0 -0
  98. {piloop-0.2.0 → piloop-0.2.1}/examples/plugins/dir-store/pyproject.toml +0 -0
  99. {piloop-0.2.0 → piloop-0.2.1}/examples/plugins/min-gain/README.md +0 -0
  100. {piloop-0.2.0 → piloop-0.2.1}/examples/plugins/min-gain/piloop_min_gain/__init__.py +0 -0
  101. {piloop-0.2.0 → piloop-0.2.1}/examples/plugins/min-gain/pyproject.toml +0 -0
  102. {piloop-0.2.0 → piloop-0.2.1}/examples/plugins/nice-runtime/README.md +0 -0
  103. {piloop-0.2.0 → piloop-0.2.1}/examples/plugins/nice-runtime/piloop_nice/__init__.py +0 -0
  104. {piloop-0.2.0 → piloop-0.2.1}/examples/plugins/nice-runtime/pyproject.toml +0 -0
  105. {piloop-0.2.0 → piloop-0.2.1}/examples/plugins/no-unit-regression/README.md +0 -0
  106. {piloop-0.2.0 → piloop-0.2.1}/examples/plugins/no-unit-regression/piloop_no_unit_regression/__init__.py +0 -0
  107. {piloop-0.2.0 → piloop-0.2.1}/examples/plugins/no-unit-regression/pyproject.toml +0 -0
  108. {piloop-0.2.0 → piloop-0.2.1}/examples/plugins/stop-after-keeps/README.md +0 -0
  109. {piloop-0.2.0 → piloop-0.2.1}/examples/plugins/stop-after-keeps/piloop_stop_after_keeps/__init__.py +0 -0
  110. {piloop-0.2.0 → piloop-0.2.1}/examples/plugins/stop-after-keeps/pyproject.toml +0 -0
  111. {piloop-0.2.0 → piloop-0.2.1}/examples/plugins/verdict-checks/README.md +0 -0
  112. {piloop-0.2.0 → piloop-0.2.1}/examples/plugins/verdict-checks/piloop_verdict_checks/__init__.py +0 -0
  113. {piloop-0.2.0 → piloop-0.2.1}/examples/plugins/verdict-checks/piloop_verdict_checks/contract.py +0 -0
  114. {piloop-0.2.0 → piloop-0.2.1}/examples/plugins/verdict-checks/pyproject.toml +0 -0
  115. {piloop-0.2.0 → piloop-0.2.1}/install.sh +0 -0
  116. {piloop-0.2.0 → piloop-0.2.1}/piloop/__init__.py +0 -0
  117. {piloop-0.2.0 → piloop-0.2.1}/piloop/__main__.py +0 -0
  118. {piloop-0.2.0 → piloop-0.2.1}/piloop/agents/__init__.py +0 -0
  119. {piloop-0.2.0 → piloop-0.2.1}/piloop/agents/capture.py +0 -0
  120. {piloop-0.2.0 → piloop-0.2.1}/piloop/agents/launcher.py +0 -0
  121. {piloop-0.2.0 → piloop-0.2.1}/piloop/agents/prompts/implementer.md +0 -0
  122. {piloop-0.2.0 → piloop-0.2.1}/piloop/agents/prompts/research.md +0 -0
  123. {piloop-0.2.0 → piloop-0.2.1}/piloop/agents/prompts/scout.md +0 -0
  124. {piloop-0.2.0 → piloop-0.2.1}/piloop/agents/prompts/sql_procedures.md +0 -0
  125. {piloop-0.2.0 → piloop-0.2.1}/piloop/agents/prompts/watchdog.md +0 -0
  126. {piloop-0.2.0 → piloop-0.2.1}/piloop/agents/prompts/watchdog_incident.md +0 -0
  127. {piloop-0.2.0 → piloop-0.2.1}/piloop/agents/prompts/watchdog_progress.md +0 -0
  128. {piloop-0.2.0 → piloop-0.2.1}/piloop/agents/refill.py +0 -0
  129. {piloop-0.2.0 → piloop-0.2.1}/piloop/agents/roles.py +0 -0
  130. {piloop-0.2.0 → piloop-0.2.1}/piloop/agents/scout.py +0 -0
  131. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/__init__.py +0 -0
  132. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/archive.py +0 -0
  133. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/campaign_types.py +0 -0
  134. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/campaigns.py +0 -0
  135. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/ideas.py +0 -0
  136. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/inbox.py +0 -0
  137. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/memory.py +0 -0
  138. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/ops.py +0 -0
  139. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/spend.py +0 -0
  140. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/stop.py +0 -0
  141. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/campaign/.entire/.gitignore +0 -0
  142. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/campaign/.entire/settings.json +0 -0
  143. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/campaign/brief.md +0 -0
  144. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/campaign/evaluate.py +0 -0
  145. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/campaign/piloop.toml +0 -0
  146. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/enwik8/.entire/.gitignore +0 -0
  147. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/enwik8/.entire/settings.json +0 -0
  148. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/enwik8/brief.md +0 -0
  149. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/enwik8/compressor.py +0 -0
  150. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/enwik8/evaluate.py +0 -0
  151. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/enwik8/piloop.toml +0 -0
  152. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/enwik8/pyproject.toml +0 -0
  153. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/titanic-tracks/.entire/.gitignore +0 -0
  154. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/titanic-tracks/.entire/settings.json +0 -0
  155. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/titanic-tracks/brief.md +0 -0
  156. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/titanic-tracks/briefs/accuracy.md +0 -0
  157. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/titanic-tracks/briefs/cost.md +0 -0
  158. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/titanic-tracks/evaluate.py +0 -0
  159. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/titanic-tracks/piloop.toml +0 -0
  160. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/titanic-tracks/pyproject.toml +0 -0
  161. {piloop-0.2.0 → piloop-0.2.1}/piloop/campaign/templates/titanic-tracks/solve.py +0 -0
  162. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/__init__.py +0 -0
  163. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/agents.py +0 -0
  164. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/campaign.py +0 -0
  165. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/candidate.py +0 -0
  166. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/common.py +0 -0
  167. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/daemon.py +0 -0
  168. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/database.py +0 -0
  169. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/doctor.py +0 -0
  170. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/evaluation.py +0 -0
  171. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/events.py +0 -0
  172. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/idea.py +0 -0
  173. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/inbox.py +0 -0
  174. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/install.py +0 -0
  175. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/main.py +0 -0
  176. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/measurement.py +0 -0
  177. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/memory.py +0 -0
  178. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/plugins.py +0 -0
  179. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/skills.py +0 -0
  180. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/store.py +0 -0
  181. {piloop-0.2.0 → piloop-0.2.1}/piloop/cli/upgrade.py +0 -0
  182. {piloop-0.2.0 → piloop-0.2.1}/piloop/config.py +0 -0
  183. {piloop-0.2.0 → piloop-0.2.1}/piloop/daemon/__init__.py +0 -0
  184. {piloop-0.2.0 → piloop-0.2.1}/piloop/daemon/archiver.py +0 -0
  185. {piloop-0.2.0 → piloop-0.2.1}/piloop/daemon/main.py +0 -0
  186. {piloop-0.2.0 → piloop-0.2.1}/piloop/daemon/run_executor.py +0 -0
  187. {piloop-0.2.0 → piloop-0.2.1}/piloop/daemon/scheduler.py +0 -0
  188. {piloop-0.2.0 → piloop-0.2.1}/piloop/daemon/serve.py +0 -0
  189. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/__init__.py +0 -0
  190. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/actor_triggers.sql +0 -0
  191. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/events.py +0 -0
  192. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/env.py +0 -0
  193. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/script.py.mako +0 -0
  194. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/versions/0001_initial.py +0 -0
  195. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/versions/0002_role_names.py +0 -0
  196. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/versions/0003_unmeasured.py +0 -0
  197. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/versions/0004_run_roles.py +0 -0
  198. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/versions/0005_recovered.py +0 -0
  199. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/versions/0006_research_memory.py +0 -0
  200. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/versions/0007_lessons.py +0 -0
  201. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/versions/0008_archives.py +0 -0
  202. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/versions/0009_archive_pruning.py +0 -0
  203. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/versions/0010_run_scoring.py +0 -0
  204. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/versions/0011_role_keys.py +0 -0
  205. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/versions/0012_codex_input.py +0 -0
  206. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/versions/0013_evaluations.py +0 -0
  207. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/versions/0014_pause_a_project.py +0 -0
  208. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/versions/0015_campaign_tree.py +0 -0
  209. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/versions/0016_campaigns.py +0 -0
  210. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/versions/0017_evaluator_runner.py +0 -0
  211. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/migrations/versions/0018_agent_sessions.py +0 -0
  212. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/models.py +0 -0
  213. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/session.py +0 -0
  214. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/sql.py +0 -0
  215. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/triggers/__init__.py +0 -0
  216. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/triggers/campaigns.py +0 -0
  217. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/triggers/changelog.py +0 -0
  218. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/triggers/ddl.py +0 -0
  219. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/triggers/fts.py +0 -0
  220. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/triggers/immutable.py +0 -0
  221. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/triggers/legacy.py +0 -0
  222. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/triggers/links.py +0 -0
  223. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/triggers/provenance.py +0 -0
  224. {piloop-0.2.0 → piloop-0.2.1}/piloop/db/triggers/roles.py +0 -0
  225. {piloop-0.2.0 → piloop-0.2.1}/piloop/deprecated.py +0 -0
  226. {piloop-0.2.0 → piloop-0.2.1}/piloop/git.py +0 -0
  227. {piloop-0.2.0 → piloop-0.2.1}/piloop/harnesses.py +0 -0
  228. {piloop-0.2.0 → piloop-0.2.1}/piloop/mcp/__init__.py +0 -0
  229. {piloop-0.2.0 → piloop-0.2.1}/piloop/mcp/claude.py +0 -0
  230. {piloop-0.2.0 → piloop-0.2.1}/piloop/mcp/codex.py +0 -0
  231. {piloop-0.2.0 → piloop-0.2.1}/piloop/mcp/pi.py +0 -0
  232. {piloop-0.2.0 → piloop-0.2.1}/piloop/otel.py +0 -0
  233. {piloop-0.2.0 → piloop-0.2.1}/piloop/plugins/__init__.py +0 -0
  234. {piloop-0.2.0 → piloop-0.2.1}/piloop/plugins/builtin/__init__.py +0 -0
  235. {piloop-0.2.0 → piloop-0.2.1}/piloop/plugins/builtin/roles.py +0 -0
  236. {piloop-0.2.0 → piloop-0.2.1}/piloop/plugins/builtin/stop.py +0 -0
  237. {piloop-0.2.0 → piloop-0.2.1}/piloop/plugins/builtin/verdict.py +0 -0
  238. {piloop-0.2.0 → piloop-0.2.1}/piloop/plugins/contracts/__init__.py +0 -0
  239. {piloop-0.2.0 → piloop-0.2.1}/piloop/plugins/contracts/runtime.py +0 -0
  240. {piloop-0.2.0 → piloop-0.2.1}/piloop/plugins/contracts/stop.py +0 -0
  241. {piloop-0.2.0 → piloop-0.2.1}/piloop/plugins/contracts/store.py +0 -0
  242. {piloop-0.2.0 → piloop-0.2.1}/piloop/plugins/contracts/verdict.py +0 -0
  243. {piloop-0.2.0 → piloop-0.2.1}/piloop/proc.py +0 -0
  244. {piloop-0.2.0 → piloop-0.2.1}/piloop/reports/__init__.py +0 -0
  245. {piloop-0.2.0 → piloop-0.2.1}/piloop/reports/feed.py +0 -0
  246. {piloop-0.2.0 → piloop-0.2.1}/piloop/reports/history.py +0 -0
  247. {piloop-0.2.0 → piloop-0.2.1}/piloop/reports/overview.py +0 -0
  248. {piloop-0.2.0 → piloop-0.2.1}/piloop/reports/pack.py +0 -0
  249. {piloop-0.2.0 → piloop-0.2.1}/piloop/reports/wake.py +0 -0
  250. {piloop-0.2.0 → piloop-0.2.1}/piloop/runtime/__init__.py +0 -0
  251. {piloop-0.2.0 → piloop-0.2.1}/piloop/runtime/factory.py +0 -0
  252. {piloop-0.2.0 → piloop-0.2.1}/piloop/runtime/herdr.py +0 -0
  253. {piloop-0.2.0 → piloop-0.2.1}/piloop/runtime/subprocess.py +0 -0
  254. {piloop-0.2.0 → piloop-0.2.1}/piloop/runtime/tags.py +0 -0
  255. {piloop-0.2.0 → piloop-0.2.1}/piloop/scoring/__init__.py +0 -0
  256. {piloop-0.2.0 → piloop-0.2.1}/piloop/scoring/evaluate.py +0 -0
  257. {piloop-0.2.0 → piloop-0.2.1}/piloop/scoring/ledger.py +0 -0
  258. {piloop-0.2.0 → piloop-0.2.1}/piloop/scoring/queue.py +0 -0
  259. {piloop-0.2.0 → piloop-0.2.1}/piloop/settings.py +0 -0
  260. {piloop-0.2.0 → piloop-0.2.1}/piloop/store/__init__.py +0 -0
  261. {piloop-0.2.0 → piloop-0.2.1}/piloop/store/config.py +0 -0
  262. {piloop-0.2.0 → piloop-0.2.1}/piloop/store/contract.py +0 -0
  263. {piloop-0.2.0 → piloop-0.2.1}/piloop/store/gcs.py +0 -0
  264. {piloop-0.2.0 → piloop-0.2.1}/piloop/store/s3.py +0 -0
  265. {piloop-0.2.0 → piloop-0.2.1}/piloop/store/tree.py +0 -0
  266. {piloop-0.2.0 → piloop-0.2.1}/piloop/text.py +0 -0
  267. {piloop-0.2.0 → piloop-0.2.1}/piloop/triggers.py +0 -0
  268. {piloop-0.2.0 → piloop-0.2.1}/piloop/usage/__init__.py +0 -0
  269. {piloop-0.2.0 → piloop-0.2.1}/piloop/usage/jsonl.py +0 -0
  270. {piloop-0.2.0 → piloop-0.2.1}/piloop/usage/tallies/__init__.py +0 -0
  271. {piloop-0.2.0 → piloop-0.2.1}/piloop/usage/tallies/claude.py +0 -0
  272. {piloop-0.2.0 → piloop-0.2.1}/piloop/usage/tallies/codex.py +0 -0
  273. {piloop-0.2.0 → piloop-0.2.1}/piloop/usage/tallies/pi.py +0 -0
  274. {piloop-0.2.0 → piloop-0.2.1}/piloop/version.py +0 -0
  275. {piloop-0.2.0 → piloop-0.2.1}/piloop/watch/__init__.py +0 -0
  276. {piloop-0.2.0 → piloop-0.2.1}/piloop/watch/app.py +0 -0
  277. {piloop-0.2.0 → piloop-0.2.1}/piloop/watch/panels.py +0 -0
  278. {piloop-0.2.0 → piloop-0.2.1}/scripts/db_volume.py +0 -0
  279. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/__init__.py +0 -0
  280. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/actor_triggers.py +0 -0
  281. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/capabilities.py +0 -0
  282. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/configuration.py +0 -0
  283. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/cwd_encoders.py +0 -0
  284. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/data_model.py +0 -0
  285. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/evaluate_examples.py +0 -0
  286. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/example_dir_store.py +0 -0
  287. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/example_min_gain.py +0 -0
  288. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/example_nice_runtime.py +0 -0
  289. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/example_no_unit_regression.py +0 -0
  290. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/example_stop_after_keeps.py +0 -0
  291. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/example_verdict_checks.py +0 -0
  292. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/harnesses.py +0 -0
  293. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/herdr_settings.py +0 -0
  294. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/imports.py +0 -0
  295. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/markdown.py +0 -0
  296. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/mcp_keys.py +0 -0
  297. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/plugin_examples.py +0 -0
  298. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/queue_keys.py +0 -0
  299. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/readers.py +0 -0
  300. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/renderers.py +0 -0
  301. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/role_defaults.py +0 -0
  302. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/role_keys.py +0 -0
  303. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/roles.py +0 -0
  304. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/run_role_keys.py +0 -0
  305. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/runtime_protocol.py +0 -0
  306. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/runtimes.py +0 -0
  307. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/schema.py +0 -0
  308. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/settings.py +0 -0
  309. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/states.py +0 -0
  310. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/stop.py +0 -0
  311. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/storage_backends.py +0 -0
  312. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/sweep_role_keys.py +0 -0
  313. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/tallies.py +0 -0
  314. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate/triggers.py +0 -0
  315. {piloop-0.2.0 → piloop-0.2.1}/scripts/generate_all.py +0 -0
  316. {piloop-0.2.0 → piloop-0.2.1}/scripts/screenshots.py +0 -0
  317. {piloop-0.2.0 → piloop-0.2.1}/scripts/xai_search_mcp.py +0 -0
  318. {piloop-0.2.0 → piloop-0.2.1}/skills/piloop-operate/SKILL.md +0 -0
  319. {piloop-0.2.0 → piloop-0.2.1}/skills/piloop-review/SKILL.md +0 -0
  320. {piloop-0.2.0 → piloop-0.2.1}/skills/piloop-setup/SKILL.md +0 -0
  321. {piloop-0.2.0 → piloop-0.2.1}/tests/agents/test_capture.py +0 -0
  322. {piloop-0.2.0 → piloop-0.2.1}/tests/agents/test_launcher.py +0 -0
  323. {piloop-0.2.0 → piloop-0.2.1}/tests/agents/test_scout.py +0 -0
  324. {piloop-0.2.0 → piloop-0.2.1}/tests/campaign/test_archive.py +0 -0
  325. {piloop-0.2.0 → piloop-0.2.1}/tests/campaign/test_campaigns.py +0 -0
  326. {piloop-0.2.0 → piloop-0.2.1}/tests/campaign/test_inbox.py +0 -0
  327. {piloop-0.2.0 → piloop-0.2.1}/tests/campaign/test_memory.py +0 -0
  328. {piloop-0.2.0 → piloop-0.2.1}/tests/campaign/test_ops.py +0 -0
  329. {piloop-0.2.0 → piloop-0.2.1}/tests/campaign/test_spend.py +0 -0
  330. {piloop-0.2.0 → piloop-0.2.1}/tests/campaign/test_stop.py +0 -0
  331. {piloop-0.2.0 → piloop-0.2.1}/tests/cli/test_cli.py +0 -0
  332. {piloop-0.2.0 → piloop-0.2.1}/tests/cli/test_control_cli.py +0 -0
  333. {piloop-0.2.0 → piloop-0.2.1}/tests/cli/test_doctor.py +0 -0
  334. {piloop-0.2.0 → piloop-0.2.1}/tests/cli/test_events.py +0 -0
  335. {piloop-0.2.0 → piloop-0.2.1}/tests/cli/test_skills.py +0 -0
  336. {piloop-0.2.0 → piloop-0.2.1}/tests/cli/test_store_cli.py +0 -0
  337. {piloop-0.2.0 → piloop-0.2.1}/tests/conftest.py +0 -0
  338. {piloop-0.2.0 → piloop-0.2.1}/tests/daemon/test_archiver.py +0 -0
  339. {piloop-0.2.0 → piloop-0.2.1}/tests/daemon/test_archiving.py +0 -0
  340. {piloop-0.2.0 → piloop-0.2.1}/tests/daemon/test_control.py +0 -0
  341. {piloop-0.2.0 → piloop-0.2.1}/tests/daemon/test_daemon.py +0 -0
  342. {piloop-0.2.0 → piloop-0.2.1}/tests/daemon/test_evaluation_queue.py +0 -0
  343. {piloop-0.2.0 → piloop-0.2.1}/tests/daemon/test_research.py +0 -0
  344. {piloop-0.2.0 → piloop-0.2.1}/tests/daemon/test_roles.py +0 -0
  345. {piloop-0.2.0 → piloop-0.2.1}/tests/daemon/test_run_executor.py +0 -0
  346. {piloop-0.2.0 → piloop-0.2.1}/tests/daemon/test_serve.py +0 -0
  347. {piloop-0.2.0 → piloop-0.2.1}/tests/daemon/test_tracks_e2e.py +0 -0
  348. {piloop-0.2.0 → piloop-0.2.1}/tests/daemon/test_triggers.py +0 -0
  349. {piloop-0.2.0 → piloop-0.2.1}/tests/db/test_db_triggers.py +0 -0
  350. {piloop-0.2.0 → piloop-0.2.1}/tests/db/test_fts.py +0 -0
  351. {piloop-0.2.0 → piloop-0.2.1}/tests/db/test_migrations.py +0 -0
  352. {piloop-0.2.0 → piloop-0.2.1}/tests/db/test_plans.py +0 -0
  353. {piloop-0.2.0 → piloop-0.2.1}/tests/db/test_sql.py +0 -0
  354. {piloop-0.2.0 → piloop-0.2.1}/tests/e2e/campaign.py +0 -0
  355. {piloop-0.2.0 → piloop-0.2.1}/tests/e2e/conftest.py +0 -0
  356. {piloop-0.2.0 → piloop-0.2.1}/tests/e2e/inventory.py +0 -0
  357. {piloop-0.2.0 → piloop-0.2.1}/tests/e2e/test_lifecycle.py +0 -0
  358. {piloop-0.2.0 → piloop-0.2.1}/tests/e2e/test_upgrade.py +0 -0
  359. {piloop-0.2.0 → piloop-0.2.1}/tests/fixtures/__init__.py +0 -0
  360. {piloop-0.2.0 → piloop-0.2.1}/tests/fixtures/auditor.md +0 -0
  361. {piloop-0.2.0 → piloop-0.2.1}/tests/fixtures/config_0005.json +0 -0
  362. {piloop-0.2.0 → piloop-0.2.1}/tests/fixtures/fake_bin.py +0 -0
  363. {piloop-0.2.0 → piloop-0.2.1}/tests/fixtures/fake_entire.py +0 -0
  364. {piloop-0.2.0 → piloop-0.2.1}/tests/fixtures/fake_herdr.py +0 -0
  365. {piloop-0.2.0 → piloop-0.2.1}/tests/fixtures/hold_lock.py +0 -0
  366. {piloop-0.2.0 → piloop-0.2.1}/tests/fixtures/plugin.py +0 -0
  367. {piloop-0.2.0 → piloop-0.2.1}/tests/fixtures/said/claude.jsonl +0 -0
  368. {piloop-0.2.0 → piloop-0.2.1}/tests/fixtures/said/codex.jsonl +0 -0
  369. {piloop-0.2.0 → piloop-0.2.1}/tests/fixtures/said/pi.jsonl +0 -0
  370. {piloop-0.2.0 → piloop-0.2.1}/tests/fixtures/sessions/claude.jsonl +0 -0
  371. {piloop-0.2.0 → piloop-0.2.1}/tests/fixtures/sessions/codex.jsonl +0 -0
  372. {piloop-0.2.0 → piloop-0.2.1}/tests/fixtures/sessions/pi.jsonl +0 -0
  373. {piloop-0.2.0 → piloop-0.2.1}/tests/fixtures/templates/piloop-0.1.0.toml +0 -0
  374. {piloop-0.2.0 → piloop-0.2.1}/tests/fixtures/templates/piloop-0.2.0.dev.toml +0 -0
  375. {piloop-0.2.0 → piloop-0.2.1}/tests/mcp/test_mcp.py +0 -0
  376. {piloop-0.2.0 → piloop-0.2.1}/tests/reports/test_feed.py +0 -0
  377. {piloop-0.2.0 → piloop-0.2.1}/tests/reports/test_history.py +0 -0
  378. {piloop-0.2.0 → piloop-0.2.1}/tests/reports/test_overview.py +0 -0
  379. {piloop-0.2.0 → piloop-0.2.1}/tests/reports/test_pack.py +0 -0
  380. {piloop-0.2.0 → piloop-0.2.1}/tests/reports/test_pack_walk.py +0 -0
  381. {piloop-0.2.0 → piloop-0.2.1}/tests/reports/test_tracks.py +0 -0
  382. {piloop-0.2.0 → piloop-0.2.1}/tests/reports/test_wake.py +0 -0
  383. {piloop-0.2.0 → piloop-0.2.1}/tests/runtime/test_dispatch.py +0 -0
  384. {piloop-0.2.0 → piloop-0.2.1}/tests/runtime/test_herdr.py +0 -0
  385. {piloop-0.2.0 → piloop-0.2.1}/tests/runtime/test_subprocess.py +0 -0
  386. {piloop-0.2.0 → piloop-0.2.1}/tests/runtime/test_tags.py +0 -0
  387. {piloop-0.2.0 → piloop-0.2.1}/tests/scoring/test_contract.py +0 -0
  388. {piloop-0.2.0 → piloop-0.2.1}/tests/scoring/test_evaluate.py +0 -0
  389. {piloop-0.2.0 → piloop-0.2.1}/tests/scoring/test_verdict.py +0 -0
  390. {piloop-0.2.0 → piloop-0.2.1}/tests/store/test_gcs.py +0 -0
  391. {piloop-0.2.0 → piloop-0.2.1}/tests/store/test_s3.py +0 -0
  392. {piloop-0.2.0 → piloop-0.2.1}/tests/store/test_storage_backend_contract.py +0 -0
  393. {piloop-0.2.0 → piloop-0.2.1}/tests/store/test_store.py +0 -0
  394. {piloop-0.2.0 → piloop-0.2.1}/tests/store/test_store_config.py +0 -0
  395. {piloop-0.2.0 → piloop-0.2.1}/tests/store/test_tree.py +0 -0
  396. {piloop-0.2.0 → piloop-0.2.1}/tests/test_config.py +0 -0
  397. {piloop-0.2.0 → piloop-0.2.1}/tests/test_deprecated.py +0 -0
  398. {piloop-0.2.0 → piloop-0.2.1}/tests/test_docs.py +0 -0
  399. {piloop-0.2.0 → piloop-0.2.1}/tests/test_generate_all.py +0 -0
  400. {piloop-0.2.0 → piloop-0.2.1}/tests/test_git.py +0 -0
  401. {piloop-0.2.0 → piloop-0.2.1}/tests/test_infra.py +0 -0
  402. {piloop-0.2.0 → piloop-0.2.1}/tests/test_proc.py +0 -0
  403. {piloop-0.2.0 → piloop-0.2.1}/tests/test_registry_names.py +0 -0
  404. {piloop-0.2.0 → piloop-0.2.1}/tests/test_settings.py +0 -0
  405. {piloop-0.2.0 → piloop-0.2.1}/tests/test_version.py +0 -0
  406. {piloop-0.2.0 → piloop-0.2.1}/tests/test_xai_search.py +0 -0
  407. {piloop-0.2.0 → piloop-0.2.1}/tests/usage/test_usage.py +0 -0
  408. {piloop-0.2.0 → piloop-0.2.1}/tests/watch/test_app.py +0 -0
@@ -5,6 +5,16 @@ All notable changes to piloop are in this file. The format follows
5
5
  [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Before 1.0, a minor release may contain breaking changes.
6
6
  A deprecated configuration key shows a warning for at least one minor release before it is removed.
7
7
 
8
+ ## [0.2.1](https://github.com/hiloopai/piloop/compare/v0.2.0...v0.2.1) - 2026-10-24
9
+
10
+ Upgrade to 0.2.1 before you upgrade to 0.3.0: `uv tool install 'piloop==0.2.1'`, then `piloop restart`. The running
11
+ agents keep going.
12
+
13
+ ### Fixed
14
+
15
+ - The daemon reads the installed entry points once per process, not on every tick. A 0.2.0 daemon reads them while
16
+ `piloop upgrade` installs 0.3.0, loads the plugins of 0.3.0 into its own code, and stops, with its agents.
17
+
8
18
  ## [0.2.0](https://github.com/hiloopai/piloop/compare/v0.1.0...v0.2.0) - 2026-10-21
9
19
 
10
20
  This release has breaking changes, marked **Breaking** below. Read
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: piloop
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Autoresearch for any repo: coding agents try ideas, piloop scores every commit and keeps what wins
5
5
  Project-URL: Homepage, https://github.com/hiloopai/piloop
6
6
  Project-URL: Documentation, https://piloop.autoresearch.inc
@@ -44,6 +44,7 @@ from collections.abc import Callable, Iterator
44
44
  from contextlib import ExitStack
45
45
  from dataclasses import dataclass
46
46
  from enum import StrEnum
47
+ from functools import cache
47
48
  from importlib.metadata import EntryPoint, entry_points
48
49
  from threading import RLock
49
50
  from typing import Literal, Protocol, TypeIs, get_type_hints
@@ -448,12 +449,16 @@ def _loaded(offer: Offer) -> object:
448
449
  raise PluginError(f'{offer.where} does not load: {type(e).__name__}: {e}') from e
449
450
 
450
451
 
451
- def declared() -> list[Activatable]:
452
+ @cache
453
+ def declared() -> tuple[Activatable, ...]:
452
454
  """Every capability that an installed package declares in ``CAPABILITIES``, piloop included, by provider group.
453
455
 
454
456
  A plugin declares a capability for a seam of its own the same way that piloop declares its own: an entry point
455
457
  that names the ``Capability``. Other packages provide it, and piloop lists, checks and selects it as any other.
456
458
 
459
+ The installed packages do not change while a process runs, so the entry points are read once, until ``close``.
460
+ Every validation of a ``piloop.toml`` asks for these, and the daemon validates each campaign's on every tick.
461
+
457
462
  Raises:
458
463
  PluginError: An entry point does not load, does not name a capability, or names a capability whose provider
459
464
  group another one has.
@@ -466,7 +471,7 @@ def declared() -> list[Activatable]:
466
471
  if (other := found.get(loaded.group)) is not None and other is not loaded:
467
472
  raise PluginError(f'{offer.where}: the {other.noun}s have the provider group {loaded.group} already')
468
473
  found[loaded.group] = loaded
469
- return sorted(found.values(), key=lambda c: c.group)
474
+ return tuple(sorted(found.values(), key=lambda c: c.group))
470
475
 
471
476
 
472
477
  def lookup(data: object, key: str) -> object | None:
@@ -540,6 +545,7 @@ def _activate(capability: Activatable, stack: ExitStack) -> None:
540
545
 
541
546
 
542
547
  def close() -> None:
543
- """Unregister every capability of the process, newest first. Closing twice is harmless."""
548
+ """Unregister every capability of the process, newest first, and forget ``declared``. Closing twice is harmless."""
544
549
  with _lock:
545
550
  _process.close()
551
+ declared.cache_clear()
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "piloop"
7
- version = "0.2.0"
7
+ version = "0.2.1"
8
8
  description = "Autoresearch for any repo: coding agents try ideas, piloop scores every commit and keeps what wins"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.14"
@@ -4,6 +4,7 @@ import threading
4
4
  import time
5
5
  from contextlib import closing
6
6
  from datetime import timedelta
7
+ from importlib.metadata import EntryPoints
7
8
  from pathlib import Path
8
9
 
9
10
  import pytest
@@ -57,6 +58,7 @@ from piloop.db.models import (
57
58
  from piloop.db.session import Database
58
59
  from piloop.db.triggers import DAEMON_ACTOR
59
60
  from piloop.otel import Tracer
61
+ from piloop.plugins import host as plugins
60
62
  from piloop.reports.overview import SILENT_SECONDS
61
63
  from piloop.runtime import AgentStatus, Handle, NotSteerable
62
64
  from piloop.scoring.ledger import current_evaluator, due, head, import_reference, request_remeasure
@@ -794,6 +796,25 @@ def test_a_dead_thread_is_traced_and_its_row_closed(
794
796
  assert (agent_session.state, agent_session.error) == (AgentSessionState.KILLED, 'RuntimeError: thread broke')
795
797
 
796
798
 
799
+ def test_a_tick_reads_no_entry_points(
800
+ db: Database, campaign: Campaign, runtime: ScriptRuntime, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
801
+ ) -> None:
802
+ """The installed packages do not change while a process runs: a tick reads each campaign's config without a scan."""
803
+ scheduler = make_scheduler(db, runtime, tmp_path)
804
+ scheduler.tick()
805
+ scans: list[str] = []
806
+ found = plugins.entry_points
807
+
808
+ def entry_points(*, group: str) -> EntryPoints:
809
+ scans.append(group)
810
+ return found(group=group)
811
+
812
+ monkeypatch.setattr(plugins, 'entry_points', entry_points)
813
+ scheduler.tick()
814
+ scheduler.tick()
815
+ assert scans == []
816
+
817
+
797
818
  def test_invalid_campaign_config_is_skipped_not_fatal(
798
819
  db: Database,
799
820
  campaign: Campaign,
@@ -434,6 +434,7 @@ def test_a_plugin_declares_a_capability_calls_its_providers_and_another_package_
434
434
  example(tmp_path / 'site', 'verdict-checks')
435
435
  example(tmp_path / 'site', 'no-unit-regression')
436
436
  monkeypatch.syspath_prepend(tmp_path / 'site')
437
+ plugins.close() # `declared` is cached per process
437
438
  checks = next(c for c in plugins.declared() if c.noun == 'verdict check')
438
439
  assert (checks.tier, checks.group, checks.selection) == (Tier.PURE, 'piloop_verdict_checks.checks', None)
439
440
  assert checks.sources()['no_unit_regression'].release == 'piloop-no-unit-regression 0.1.0'
@@ -1103,7 +1103,7 @@ wheels = [
1103
1103
 
1104
1104
  [[package]]
1105
1105
  name = "piloop"
1106
- version = "0.2.0"
1106
+ version = "0.2.1"
1107
1107
  source = { editable = "." }
1108
1108
  dependencies = [
1109
1109
  { name = "alembic" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes