codexloop 0.1.0__tar.gz → 0.3.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 (261) hide show
  1. {codexloop-0.1.0 → codexloop-0.3.0}/.github/workflows/ci.yml +36 -1
  2. codexloop-0.3.0/.github/workflows/docs.yml +40 -0
  3. {codexloop-0.1.0 → codexloop-0.3.0}/.github/workflows/publish-testpypi.yml +1 -0
  4. {codexloop-0.1.0 → codexloop-0.3.0}/.github/workflows/release-please.yml +15 -8
  5. {codexloop-0.1.0 → codexloop-0.3.0}/.gitignore +1 -0
  6. codexloop-0.3.0/.release-please-manifest.json +3 -0
  7. codexloop-0.3.0/CHANGELOG.md +140 -0
  8. {codexloop-0.1.0 → codexloop-0.3.0}/PKG-INFO +13 -5
  9. {codexloop-0.1.0 → codexloop-0.3.0}/README.md +12 -4
  10. codexloop-0.3.0/docs/publishing.md +74 -0
  11. codexloop-0.3.0/mkdocs.yml +44 -0
  12. {codexloop-0.1.0 → codexloop-0.3.0}/pyproject.toml +14 -1
  13. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/__init__.py +1 -1
  14. codexloop-0.3.0/src/codexloop/application/interfaces/__init__.py +75 -0
  15. codexloop-0.3.0/src/codexloop/application/interfaces/agent.py +46 -0
  16. codexloop-0.3.0/src/codexloop/application/interfaces/api.py +10 -0
  17. codexloop-0.3.0/src/codexloop/application/interfaces/control.py +21 -0
  18. {codexloop-0.1.0/src/codexloop/application/usecases → codexloop-0.3.0/src/codexloop/application/interfaces}/doctor.py +7 -9
  19. codexloop-0.3.0/src/codexloop/application/interfaces/observability.py +42 -0
  20. codexloop-0.3.0/src/codexloop/application/interfaces/permissions.py +14 -0
  21. codexloop-0.3.0/src/codexloop/application/interfaces/storage.py +31 -0
  22. codexloop-0.3.0/src/codexloop/application/interfaces/system.py +16 -0
  23. codexloop-0.3.0/src/codexloop/application/ports.py +61 -0
  24. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/application/runner.py +115 -1
  25. codexloop-0.3.0/src/codexloop/application/usecases/doctor.py +18 -0
  26. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/application/usecases/run_control.py +1 -5
  27. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/bootstrap.py +15 -2
  28. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/app.py +24 -1
  29. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/run.py +10 -1
  30. codexloop-0.3.0/src/codexloop/domain/forecast.py +271 -0
  31. codexloop-0.3.0/src/codexloop/domain/handoff_marker.py +107 -0
  32. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/domain/loop.py +31 -2
  33. codexloop-0.3.0/src/codexloop/domain/verbosity.py +80 -0
  34. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/git_savepoints.py +5 -1
  35. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/logging.py +21 -0
  36. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/rundir.py +27 -2
  37. {codexloop-0.1.0 → codexloop-0.3.0}/tests/application/fakes.py +3 -0
  38. codexloop-0.3.0/tests/application/test_interfaces_convention.py +100 -0
  39. {codexloop-0.1.0 → codexloop-0.3.0}/tests/application/test_runner.py +66 -0
  40. {codexloop-0.1.0 → codexloop-0.3.0}/tests/cli/test_app.py +15 -1
  41. codexloop-0.3.0/tests/cli/test_verbosity_flags.py +48 -0
  42. codexloop-0.3.0/tests/domain/test_forecast.py +209 -0
  43. codexloop-0.3.0/tests/domain/test_handoff_marker.py +83 -0
  44. {codexloop-0.1.0 → codexloop-0.3.0}/tests/domain/test_loop.py +73 -1
  45. codexloop-0.3.0/tests/domain/test_verbosity.py +60 -0
  46. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/api/test_providers_gateway_extra.py +2 -1
  47. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_appserver_gateway.py +9 -0
  48. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_coverage_boost.py +24 -1
  49. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_doctor_env.py +36 -0
  50. codexloop-0.3.0/tests/infrastructure/test_git_savepoints_units.py +69 -0
  51. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_logging_redact.py +41 -0
  52. codexloop-0.3.0/tests/infrastructure/test_rollout_scan.py +91 -0
  53. codexloop-0.3.0/tests/infrastructure/test_rundir_run_id.py +48 -0
  54. codexloop-0.3.0/uv.lock +2277 -0
  55. codexloop-0.1.0/.release-please-manifest.json +0 -3
  56. codexloop-0.1.0/CHANGELOG.md +0 -42
  57. codexloop-0.1.0/docs/publishing.md +0 -65
  58. codexloop-0.1.0/mkdocs.yml +0 -28
  59. codexloop-0.1.0/src/codexloop/application/ports.py +0 -158
  60. {codexloop-0.1.0 → codexloop-0.3.0}/.agents/skills/codexloop-run/SKILL.md +0 -0
  61. {codexloop-0.1.0 → codexloop-0.3.0}/.claude/skills/codexloop-run/SKILL.md +0 -0
  62. {codexloop-0.1.0 → codexloop-0.3.0}/.cursor/rules/codexloop-run.mdc +0 -0
  63. {codexloop-0.1.0 → codexloop-0.3.0}/.editorconfig +0 -0
  64. {codexloop-0.1.0 → codexloop-0.3.0}/.github/CODEOWNERS +0 -0
  65. {codexloop-0.1.0 → codexloop-0.3.0}/.pre-commit-config.yaml +0 -0
  66. {codexloop-0.1.0 → codexloop-0.3.0}/AGENTS.md +0 -0
  67. {codexloop-0.1.0 → codexloop-0.3.0}/CLAUDE.md +0 -0
  68. {codexloop-0.1.0 → codexloop-0.3.0}/CODE_OF_CONDUCT.md +0 -0
  69. {codexloop-0.1.0 → codexloop-0.3.0}/CONTRIBUTING.md +0 -0
  70. {codexloop-0.1.0 → codexloop-0.3.0}/LICENSE +0 -0
  71. {codexloop-0.1.0 → codexloop-0.3.0}/SECURITY.md +0 -0
  72. {codexloop-0.1.0 → codexloop-0.3.0}/docs/architecture/adr/0001-onion-import-linter.md +0 -0
  73. {codexloop-0.1.0 → codexloop-0.3.0}/docs/architecture/adr/0002-subprocess-codex-exec.md +0 -0
  74. {codexloop-0.1.0 → codexloop-0.3.0}/docs/architecture/adr/0003-credits-exhausted.md +0 -0
  75. {codexloop-0.1.0 → codexloop-0.3.0}/docs/architecture/adr/0004-adaptive-probe-loop.md +0 -0
  76. {codexloop-0.1.0 → codexloop-0.3.0}/docs/architecture/adr/0005-layered-capacity-probe.md +0 -0
  77. {codexloop-0.1.0 → codexloop-0.3.0}/docs/architecture/adr/0006-generated-openai-rest.md +0 -0
  78. {codexloop-0.1.0 → codexloop-0.3.0}/docs/architecture/adr/0007-default-approval-sandbox.md +0 -0
  79. {codexloop-0.1.0 → codexloop-0.3.0}/docs/architecture/adr/0008-policy-via-c-flags.md +0 -0
  80. {codexloop-0.1.0 → codexloop-0.3.0}/docs/architecture/adr/0009-optional-app-server.md +0 -0
  81. {codexloop-0.1.0 → codexloop-0.3.0}/docs/architecture/adr/0010-rollout-best-effort.md +0 -0
  82. {codexloop-0.1.0 → codexloop-0.3.0}/docs/architecture/adr/0011-never-consume-resets.md +0 -0
  83. {codexloop-0.1.0 → codexloop-0.3.0}/docs/architecture/adr/0012-minimum-codex-version.md +0 -0
  84. {codexloop-0.1.0 → codexloop-0.3.0}/docs/architecture/adr/index.md +0 -0
  85. {codexloop-0.1.0 → codexloop-0.3.0}/docs/architecture/index.md +0 -0
  86. {codexloop-0.1.0 → codexloop-0.3.0}/docs/contributing.md +0 -0
  87. {codexloop-0.1.0 → codexloop-0.3.0}/docs/getting-started.md +0 -0
  88. {codexloop-0.1.0 → codexloop-0.3.0}/docs/guides/rest-api-surface.md +0 -0
  89. {codexloop-0.1.0 → codexloop-0.3.0}/docs/index.md +0 -0
  90. {codexloop-0.1.0 → codexloop-0.3.0}/docs/plans/_shared-transplant-outline.md +0 -0
  91. {codexloop-0.1.0 → codexloop-0.3.0}/docs/plans/architecture-and-roadmap.md +0 -0
  92. {codexloop-0.1.0 → codexloop-0.3.0}/docs/plans/research-notes.md +0 -0
  93. {codexloop-0.1.0 → codexloop-0.3.0}/docs/reference/cli.md +0 -0
  94. {codexloop-0.1.0 → codexloop-0.3.0}/docs/superpowers/plans/2026-08-13-codexloop-implementation.md +0 -0
  95. {codexloop-0.1.0 → codexloop-0.3.0}/release-please-config.json +0 -0
  96. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/application/__init__.py +0 -0
  97. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/application/dto.py +0 -0
  98. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/application/usecases/__init__.py +0 -0
  99. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/application/usecases/list_threads.py +0 -0
  100. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/application/usecases/preflight.py +0 -0
  101. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/application/usecases/resume_thread.py +0 -0
  102. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/application/usecases/run_plan.py +0 -0
  103. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/__init__.py +0 -0
  104. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/asyncio.py +0 -0
  105. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/__init__.py +0 -0
  106. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/approval_cmd.py +0 -0
  107. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/capacity.py +0 -0
  108. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/cwd_cmd.py +0 -0
  109. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/doctor.py +0 -0
  110. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/effort_cmd.py +0 -0
  111. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/logs.py +0 -0
  112. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/model_cmd.py +0 -0
  113. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/prompt.py +0 -0
  114. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/reset.py +0 -0
  115. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/resume.py +0 -0
  116. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/runs.py +0 -0
  117. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/sandbox_cmd.py +0 -0
  118. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/savepoints.py +0 -0
  119. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/snapshot.py +0 -0
  120. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/status.py +0 -0
  121. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/stop.py +0 -0
  122. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/threads.py +0 -0
  123. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/unwind.py +0 -0
  124. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/commands/watch.py +0 -0
  125. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/cli/render.py +0 -0
  126. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/domain/__init__.py +0 -0
  127. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/domain/approval.py +0 -0
  128. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/domain/backoff.py +0 -0
  129. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/domain/budget.py +0 -0
  130. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/domain/capacity.py +0 -0
  131. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/domain/classify.py +0 -0
  132. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/domain/completion.py +0 -0
  133. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/domain/control.py +0 -0
  134. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/domain/error_codes.py +0 -0
  135. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/domain/errors.py +0 -0
  136. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/domain/model_profile.py +0 -0
  137. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/domain/plan.py +0 -0
  138. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/domain/savepoint.py +0 -0
  139. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/domain/savepoint_message.py +0 -0
  140. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/domain/session.py +0 -0
  141. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/domain/signals.py +0 -0
  142. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/domain/waiting.py +0 -0
  143. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/__init__.py +0 -0
  144. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/agent/__init__.py +0 -0
  145. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/agent/argv.py +0 -0
  146. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/agent/events.py +0 -0
  147. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/agent/gateway.py +0 -0
  148. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/agent/probe.py +0 -0
  149. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/agent/process.py +0 -0
  150. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/agent/schema.py +0 -0
  151. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/agent/scripted.py +0 -0
  152. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/agent/translate.py +0 -0
  153. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/api/__init__.py +0 -0
  154. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/api/api_baseline.json +0 -0
  155. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/api/binder.py +0 -0
  156. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/api/gateway.py +0 -0
  157. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/api/introspect.py +0 -0
  158. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/api/json_io.py +0 -0
  159. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/api/params.py +0 -0
  160. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/api/providers.py +0 -0
  161. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/api/registry.py +0 -0
  162. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/appserver/__init__.py +0 -0
  163. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/appserver/client.py +0 -0
  164. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/appserver/gateway.py +0 -0
  165. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/appserver/ratelimits.py +0 -0
  166. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/audit.py +0 -0
  167. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/capacity_probe.py +0 -0
  168. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/clock.py +0 -0
  169. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/config.py +0 -0
  170. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/control.py +0 -0
  171. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/doctor_env.py +0 -0
  172. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/events.py +0 -0
  173. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/lock.py +0 -0
  174. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/notify.py +0 -0
  175. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/progress.py +0 -0
  176. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/redact.py +0 -0
  177. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/rollout.py +0 -0
  178. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/snapshot.py +0 -0
  179. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/state.py +0 -0
  180. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/state_bus.py +0 -0
  181. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/infrastructure/stream_ui.py +0 -0
  182. {codexloop-0.1.0 → codexloop-0.3.0}/src/codexloop/py.typed +0 -0
  183. {codexloop-0.1.0 → codexloop-0.3.0}/tests/__init__.py +0 -0
  184. {codexloop-0.1.0 → codexloop-0.3.0}/tests/application/__init__.py +0 -0
  185. {codexloop-0.1.0 → codexloop-0.3.0}/tests/application/test_doctor.py +0 -0
  186. {codexloop-0.1.0 → codexloop-0.3.0}/tests/application/test_ports.py +0 -0
  187. {codexloop-0.1.0 → codexloop-0.3.0}/tests/application/test_usecases.py +0 -0
  188. {codexloop-0.1.0 → codexloop-0.3.0}/tests/application/test_waiting_runner.py +0 -0
  189. {codexloop-0.1.0 → codexloop-0.3.0}/tests/cli/__init__.py +0 -0
  190. {codexloop-0.1.0 → codexloop-0.3.0}/tests/cli/test_api.py +0 -0
  191. {codexloop-0.1.0 → codexloop-0.3.0}/tests/cli/test_asyncio.py +0 -0
  192. {codexloop-0.1.0 → codexloop-0.3.0}/tests/cli/test_e2e_shim.py +0 -0
  193. {codexloop-0.1.0 → codexloop-0.3.0}/tests/cli/test_ops_commands.py +0 -0
  194. {codexloop-0.1.0 → codexloop-0.3.0}/tests/conftest.py +0 -0
  195. {codexloop-0.1.0 → codexloop-0.3.0}/tests/domain/__init__.py +0 -0
  196. {codexloop-0.1.0 → codexloop-0.3.0}/tests/domain/strategies.py +0 -0
  197. {codexloop-0.1.0 → codexloop-0.3.0}/tests/domain/test_approval.py +0 -0
  198. {codexloop-0.1.0 → codexloop-0.3.0}/tests/domain/test_backoff.py +0 -0
  199. {codexloop-0.1.0 → codexloop-0.3.0}/tests/domain/test_budget.py +0 -0
  200. {codexloop-0.1.0 → codexloop-0.3.0}/tests/domain/test_capacity.py +0 -0
  201. {codexloop-0.1.0 → codexloop-0.3.0}/tests/domain/test_classify.py +0 -0
  202. {codexloop-0.1.0 → codexloop-0.3.0}/tests/domain/test_completion.py +0 -0
  203. {codexloop-0.1.0 → codexloop-0.3.0}/tests/domain/test_control.py +0 -0
  204. {codexloop-0.1.0 → codexloop-0.3.0}/tests/domain/test_error_codes.py +0 -0
  205. {codexloop-0.1.0 → codexloop-0.3.0}/tests/domain/test_model_profile.py +0 -0
  206. {codexloop-0.1.0 → codexloop-0.3.0}/tests/domain/test_plan.py +0 -0
  207. {codexloop-0.1.0 → codexloop-0.3.0}/tests/domain/test_savepoint.py +0 -0
  208. {codexloop-0.1.0 → codexloop-0.3.0}/tests/domain/test_session.py +0 -0
  209. {codexloop-0.1.0 → codexloop-0.3.0}/tests/domain/test_waiting.py +0 -0
  210. {codexloop-0.1.0 → codexloop-0.3.0}/tests/fixtures/jsonl/README.md +0 -0
  211. {codexloop-0.1.0 → codexloop-0.3.0}/tests/fixtures/jsonl/clean_completion.jsonl +0 -0
  212. {codexloop-0.1.0 → codexloop-0.3.0}/tests/fixtures/jsonl/done_with_marker.jsonl +0 -0
  213. {codexloop-0.1.0 → codexloop-0.3.0}/tests/fixtures/jsonl/huge_line.jsonl +0 -0
  214. {codexloop-0.1.0 → codexloop-0.3.0}/tests/fixtures/jsonl/malformed_line.jsonl +0 -0
  215. {codexloop-0.1.0 → codexloop-0.3.0}/tests/fixtures/jsonl/tool_heavy.jsonl +0 -0
  216. {codexloop-0.1.0 → codexloop-0.3.0}/tests/fixtures/jsonl/truncated_stream.jsonl +0 -0
  217. {codexloop-0.1.0 → codexloop-0.3.0}/tests/fixtures/jsonl/turn_failed_429_quota.jsonl +0 -0
  218. {codexloop-0.1.0 → codexloop-0.3.0}/tests/fixtures/jsonl/turn_failed_429_window.jsonl +0 -0
  219. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/__init__.py +0 -0
  220. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/api/__init__.py +0 -0
  221. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/api/test_binder.py +0 -0
  222. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/api/test_drift.py +0 -0
  223. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/api/test_gateway.py +0 -0
  224. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/api/test_introspect.py +0 -0
  225. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/api/test_json_io.py +0 -0
  226. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/api/test_params.py +0 -0
  227. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/api/test_params_extra.py +0 -0
  228. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/api/test_providers.py +0 -0
  229. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_appserver.py +0 -0
  230. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_argv.py +0 -0
  231. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_capacity_probe.py +0 -0
  232. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_config.py +0 -0
  233. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_control_and_savepoints.py +0 -0
  234. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_events.py +0 -0
  235. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_gateway.py +0 -0
  236. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_lock.py +0 -0
  237. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_probe.py +0 -0
  238. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_process.py +0 -0
  239. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_ratelimits_extra.py +0 -0
  240. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_rollout.py +0 -0
  241. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_rundir_state.py +0 -0
  242. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_scripted.py +0 -0
  243. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_snapshot.py +0 -0
  244. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_state_bus.py +0 -0
  245. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_stream_ui.py +0 -0
  246. {codexloop-0.1.0 → codexloop-0.3.0}/tests/infrastructure/test_translate.py +0 -0
  247. {codexloop-0.1.0 → codexloop-0.3.0}/tests/live/fixtures/agent_scripts/done.json +0 -0
  248. {codexloop-0.1.0 → codexloop-0.3.0}/tests/live/fixtures/agent_scripts/quota_then_topup.json +0 -0
  249. {codexloop-0.1.0 → codexloop-0.3.0}/tests/live/fixtures/agent_scripts/unknown_429.json +0 -0
  250. {codexloop-0.1.0 → codexloop-0.3.0}/tests/live/fixtures/agent_scripts/wait_long.json +0 -0
  251. {codexloop-0.1.0 → codexloop-0.3.0}/tests/live/fixtures/agent_scripts/window_then_done.json +0 -0
  252. {codexloop-0.1.0 → codexloop-0.3.0}/tests/live/system/conftest.py +0 -0
  253. {codexloop-0.1.0 → codexloop-0.3.0}/tests/live/system/test_matrix_inprocess.py +0 -0
  254. {codexloop-0.1.0 → codexloop-0.3.0}/tests/live/system/test_subprocess_smoke.py +0 -0
  255. {codexloop-0.1.0 → codexloop-0.3.0}/tests/shim/__init__.py +0 -0
  256. {codexloop-0.1.0 → codexloop-0.3.0}/tests/shim/fake_appserver.py +0 -0
  257. {codexloop-0.1.0 → codexloop-0.3.0}/tests/shim/fake_codex.py +0 -0
  258. {codexloop-0.1.0 → codexloop-0.3.0}/tests/shim/test_fake_codex.py +0 -0
  259. {codexloop-0.1.0 → codexloop-0.3.0}/tests/test_bootstrap.py +0 -0
  260. {codexloop-0.1.0 → codexloop-0.3.0}/tests/test_no_vendor_leak.py +0 -0
  261. {codexloop-0.1.0 → codexloop-0.3.0}/tests/test_packaging.py +0 -0
@@ -35,7 +35,42 @@ jobs:
35
35
  - run: lint-imports
36
36
  - run: bandit -q -r src/codexloop
37
37
  - run: pip-audit
38
- - run: pytest --cov-report=term-missing
38
+ # Per layer, not in aggregate: a blanket floor lets a well-tested domain
39
+ # hide an untested adapter. pytest-cov unions --cov scopes within one
40
+ # invocation, so each floor needs its own run.
41
+ - name: Coverage floor - domain (100%)
42
+ run: pytest -q --cov=codexloop.domain --cov-fail-under=100
43
+ - name: Coverage floor - application (100%)
44
+ run: pytest -q --cov=codexloop.application --cov-fail-under=100
45
+ - name: Coverage floor - infrastructure (100%)
46
+ run: pytest -q --cov=codexloop.infrastructure --cov-fail-under=100
47
+ - name: Coverage floor - cli (100%)
48
+ run: pytest -q --cov=codexloop.cli --cov-fail-under=100
49
+
50
+ docs:
51
+ name: MkDocs builds strictly
52
+ runs-on: ubuntu-latest
53
+ steps:
54
+ - uses: actions/checkout@v7.0.1
55
+ - uses: actions/setup-python@v7.0.0
56
+ with:
57
+ python-version: "3.12"
58
+ - run: python -m pip install --upgrade pip
59
+ - run: pip install -e ".[docs]"
60
+ - run: mkdocs build --strict
61
+
62
+ uv-lock:
63
+ name: uv.lock is in sync with pyproject.toml
64
+ runs-on: ubuntu-latest
65
+ steps:
66
+ - uses: actions/checkout@v7.0.1
67
+ - uses: actions/setup-python@v7.0.0
68
+ with:
69
+ python-version: "3.12"
70
+ - uses: astral-sh/setup-uv@v3
71
+ with:
72
+ enable-cache: true
73
+ - run: uv lock --check
39
74
 
40
75
  build:
41
76
  name: Package builds and is installable
@@ -0,0 +1,40 @@
1
+ name: Docs
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+ pages: write
11
+ id-token: write
12
+
13
+ concurrency:
14
+ group: pages
15
+ cancel-in-progress: false
16
+
17
+ jobs:
18
+ build:
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+ - uses: actions/setup-python@v5
23
+ with:
24
+ python-version: "3.12"
25
+ - run: python -m pip install --upgrade pip
26
+ - run: pip install -e ".[docs]"
27
+ - run: mkdocs build --strict
28
+ - uses: actions/upload-pages-artifact@v3
29
+ with:
30
+ path: site
31
+
32
+ deploy:
33
+ needs: build
34
+ runs-on: ubuntu-latest
35
+ environment:
36
+ name: github-pages
37
+ url: ${{ steps.deployment.outputs.page_url }}
38
+ steps:
39
+ - id: deployment
40
+ uses: actions/deploy-pages@v4
@@ -16,6 +16,7 @@ concurrency:
16
16
  jobs:
17
17
  publish:
18
18
  name: Build and publish to TestPyPI
19
+ if: ${{ github.ref == 'refs/heads/develop' }}
19
20
  runs-on: ubuntu-latest
20
21
  environment: testpypi
21
22
  steps:
@@ -5,10 +5,14 @@ on:
5
5
  branches: [main]
6
6
  workflow_dispatch:
7
7
  inputs:
8
- publish_to_testpypi:
9
- description: "Also build and publish this commit to TestPyPI (Trusted Publishing)."
8
+ publish_to_pypi:
9
+ description: "Build and publish ref to PyPI (Trusted Publishing). Use after tagging or to retry a release."
10
10
  type: boolean
11
11
  default: false
12
+ publish_tag:
13
+ description: "Git tag to build/publish when publish_to_pypi=true"
14
+ type: string
15
+ default: "v0.2.0"
12
16
 
13
17
  permissions:
14
18
  contents: write
@@ -22,9 +26,12 @@ jobs:
22
26
  release_created: ${{ steps.release.outputs.release_created }}
23
27
  tag_name: ${{ steps.release.outputs.tag_name }}
24
28
  steps:
25
- - uses: googleapis/release-please-action@v4
29
+ - uses: googleapis/release-please-action@v5
26
30
  id: release
27
31
  with:
32
+ # Repo default branch is develop; releases must target main only
33
+ # (feat → develop → TestPyPI → main → tag/PyPI).
34
+ target-branch: main
28
35
  release-type: python
29
36
  config-file: release-please-config.json
30
37
  manifest-file: .release-please-manifest.json
@@ -52,15 +59,17 @@ jobs:
52
59
  packages-dir: dist/
53
60
  print-hash: true
54
61
 
55
- publish-testpypi-manual:
56
- if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish_to_testpypi }}
62
+ publish-pypi-manual:
63
+ if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish_to_pypi }}
57
64
  runs-on: ubuntu-latest
58
- environment: testpypi
65
+ environment: pypi
59
66
  permissions:
60
67
  id-token: write
61
68
  contents: read
62
69
  steps:
63
70
  - uses: actions/checkout@v4
71
+ with:
72
+ ref: ${{ inputs.publish_tag }}
64
73
  - uses: actions/setup-python@v5
65
74
  with:
66
75
  python-version: "3.12"
@@ -69,7 +78,5 @@ jobs:
69
78
  - run: twine check --strict dist/*
70
79
  - uses: pypa/gh-action-pypi-publish@release/v1
71
80
  with:
72
- repository-url: https://test.pypi.org/legacy/
73
81
  packages-dir: dist/
74
- skip-existing: true
75
82
  print-hash: true
@@ -46,3 +46,4 @@ site/
46
46
 
47
47
  # --- SDD scratch ---
48
48
  .superpowers/
49
+ .venv-docs/
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.3.0"
3
+ }
@@ -0,0 +1,140 @@
1
+ # Changelog
2
+
3
+ ## [0.3.0](https://github.com/adammatthewsteinberger/codexloop/compare/v0.2.0...v0.3.0) (2026-08-16)
4
+
5
+
6
+ ### Features
7
+
8
+ * add a -v/-q verbosity ladder and third-party log control ([b58dfc0](https://github.com/adammatthewsteinberger/codexloop/commit/b58dfc017ce9af34af07cb390ea9a8efd67435d3))
9
+ * add capacity forecasting (measurement only, disabled by default) ([c2a362b](https://github.com/adammatthewsteinberger/codexloop/commit/c2a362bcbd111e7f87e5fb2534eb1687e50dc42d))
10
+ * add the wind-down decision to the run loop state machine ([033b5b2](https://github.com/adammatthewsteinberger/codexloop/commit/033b5b2ecece721832f31cd08e103738c193c812))
11
+ * let the caller name a run with --run-id ([e22c2d0](https://github.com/adammatthewsteinberger/codexloop/commit/e22c2d05c03db5be84ecbbd544da418130c1023c))
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * **tests:** remove residual SHA-collision flake in savepoints test ([#20](https://github.com/adammatthewsteinberger/codexloop/issues/20)) ([b375f71](https://github.com/adammatthewsteinberger/codexloop/commit/b375f71ba5ebda62f178bdc39bb619418932dedf))
17
+
18
+ ## [0.3.0](https://github.com/adammatthewsteinberger/codexloop/compare/v0.2.0...v0.3.0) (2026-08-16)
19
+
20
+
21
+ ### Features
22
+
23
+ * add a -v/-q verbosity ladder and third-party log control ([b58dfc0](https://github.com/adammatthewsteinberger/codexloop/commit/b58dfc017ce9af34af07cb390ea9a8efd67435d3))
24
+ * add capacity forecasting (measurement only, disabled by default) ([c2a362b](https://github.com/adammatthewsteinberger/codexloop/commit/c2a362bcbd111e7f87e5fb2534eb1687e50dc42d))
25
+ * add the wind-down decision to the run loop state machine ([033b5b2](https://github.com/adammatthewsteinberger/codexloop/commit/033b5b2ecece721832f31cd08e103738c193c812))
26
+ * let the caller name a run with --run-id ([e22c2d0](https://github.com/adammatthewsteinberger/codexloop/commit/e22c2d05c03db5be84ecbbd544da418130c1023c))
27
+
28
+
29
+ ### Bug Fixes
30
+
31
+ * **tests:** remove residual SHA-collision flake in savepoints test ([#20](https://github.com/adammatthewsteinberger/codexloop/issues/20)) ([b375f71](https://github.com/adammatthewsteinberger/codexloop/commit/b375f71ba5ebda62f178bdc39bb619418932dedf))
32
+
33
+ ## [0.2.0](https://github.com/adammatthewsteinberger/codexloop/compare/v0.1.1...v0.2.0) (2026-08-14)
34
+
35
+
36
+ ### Features
37
+
38
+ * add app-server rate-limit probe client ([a30ef93](https://github.com/adammatthewsteinberger/codexloop/commit/a30ef9377685ef9aea8f5096e1759b0f6293574e))
39
+ * add application ports and fakes ([33e721d](https://github.com/adammatthewsteinberger/codexloop/commit/33e721d0dab21b38c614ab71ea7c3e47a8126fb3))
40
+ * add autonomous runner and run/resume use cases ([bd36f45](https://github.com/adammatthewsteinberger/codexloop/commit/bd36f457548c5969f0fd37453c2d1ab5727d3302))
41
+ * add backoff and adaptive wait policy ([43c70c6](https://github.com/adammatthewsteinberger/codexloop/commit/43c70c68396255e10c61907497c53dd0d1c2ba63))
42
+ * add bootstrap and core CLI commands ([6b6aafc](https://github.com/adammatthewsteinberger/codexloop/commit/6b6aafc94f8d2513282389f154682b1b5a97bcee))
43
+ * add capacity value objects ([1aa3fed](https://github.com/adammatthewsteinberger/codexloop/commit/1aa3fede743d6c5db518f869d03826788c64da5b))
44
+ * add clock, logging, config, rundir, state, and lock adapters ([8f7e4ad](https://github.com/adammatthewsteinberger/codexloop/commit/8f7e4ad1aad0f9a754e7ff5777898bfe5a35c5cd))
45
+ * add codex argv builder ([42ab842](https://github.com/adammatthewsteinberger/codexloop/commit/42ab8426e676b0c6b59bb655bfc94e4a607338ba))
46
+ * add control plane, savepoints, and ops CLI ([512e03f](https://github.com/adammatthewsteinberger/codexloop/commit/512e03f24eddf226425326b992eacc4732f1bc7b))
47
+ * add ephemeral read-only exec capacity probe ([427620b](https://github.com/adammatthewsteinberger/codexloop/commit/427620bda645389caf571bcef010d269d3457093))
48
+ * add error hierarchy and OpenAI error-code taxonomy ([1bf5aa2](https://github.com/adammatthewsteinberger/codexloop/commit/1bf5aa2f2805c80aeba0f37fbe6da1dcb4a59585))
49
+ * add generated OpenAI REST CLI surface with drift gate ([53320f8](https://github.com/adammatthewsteinberger/codexloop/commit/53320f82512869b43075d6eeaf3f6fe73a06a3dd))
50
+ * add optional app-server gateway, stream UI, docs, and release scaffolding ([23bfddf](https://github.com/adammatthewsteinberger/codexloop/commit/23bfddfb169cfb37e8fe60a9a80bd7f9b644bba9))
51
+ * add plan, budget, session, profile, approval, and control types ([07a8188](https://github.com/adammatthewsteinberger/codexloop/commit/07a8188207fa6fbac5f85114d891b266b6be1bf9))
52
+ * add read-only CODEX_HOME rollout tail ([071d6ab](https://github.com/adammatthewsteinberger/codexloop/commit/071d6abe526935893d7d330909e96a308e5203b2))
53
+ * add run-loop state machine ([582144f](https://github.com/adammatthewsteinberger/codexloop/commit/582144fcd2b5d3c327f6af36c74307a9a8818966))
54
+ * add scripted system harness and test-agent gate ([68a7ebf](https://github.com/adammatthewsteinberger/codexloop/commit/68a7ebf9483013f5e7fae4ff98ff2b0f5da843f0))
55
+ * add three-layer completion evaluation ([eee2cc3](https://github.com/adammatthewsteinberger/codexloop/commit/eee2cc3a70562126c438e1a1ba842abca9aa0db6))
56
+ * classify turn signals into capacity states ([f7c4162](https://github.com/adammatthewsteinberger/codexloop/commit/f7c4162048b62f83a7b7ea3f99474605f18376ef))
57
+ * implement codexloop M1–M5 (onion runner + REST + docs) ([1dbef91](https://github.com/adammatthewsteinberger/codexloop/commit/1dbef9118097d8b8210f6a770df8c4c05956f6ce))
58
+ * parse codex exec JSONL events ([1cdc76c](https://github.com/adammatthewsteinberger/codexloop/commit/1cdc76c754f0e0f023f7dc94472be59f9776d3f5))
59
+ * supervise codex subprocess with concurrent pumps ([1c95f6e](https://github.com/adammatthewsteinberger/codexloop/commit/1c95f6e6fe628daefe0256e5ba5fb921bfd595a5))
60
+ * translate JSONL and drive codex exec gateway ([6a1842c](https://github.com/adammatthewsteinberger/codexloop/commit/6a1842c3bab3b9eb57d052b2bb8f1c45b919b69f))
61
+ * wire composite capacity probe and adaptive wait loop ([ab682b1](https://github.com/adammatthewsteinberger/codexloop/commit/ab682b16130829e3ae7a523597213c33509dec22))
62
+
63
+
64
+ ### Bug Fixes
65
+
66
+ * jitter throttle waits above Retry-After ([666a4e6](https://github.com/adammatthewsteinberger/codexloop/commit/666a4e6c3d73f277946e866d33866091c225e1c8))
67
+ * only break session locks for known-dead pids ([712b0f4](https://github.com/adammatthewsteinberger/codexloop/commit/712b0f4a4b25d83ba27c0ca53d8278e6961efbd9))
68
+ * pin release-please to main ([4c974a2](https://github.com/adammatthewsteinberger/codexloop/commit/4c974a243f98d0790325929fd124c4aca72f04f7))
69
+ * pin release-please to main and Node 24 action ([cf19789](https://github.com/adammatthewsteinberger/codexloop/commit/cf19789c9ed4fc179f88ef6176f8b05859d05cb8))
70
+ * preserve remaining work across capacity-rejected turns ([d2d10c3](https://github.com/adammatthewsteinberger/codexloop/commit/d2d10c36a93084a36f48509433d9bb6865172fde))
71
+ * resolve all-digit SHA prefixes as save-point SHAs ([43cdde7](https://github.com/adammatthewsteinberger/codexloop/commit/43cdde7d5f65910c06ef6273e64987a391ce0488))
72
+ * seal onion contracts and order drain before signals ([cecf827](https://github.com/adammatthewsteinberger/codexloop/commit/cecf827e841d11df0fb34c71724415970da3ab7d))
73
+ * stabilize CI help and process-group cancel tests ([3fe2c6d](https://github.com/adammatthewsteinberger/codexloop/commit/3fe2c6d09f94adb0de528a74364a0d9d177ee77b))
74
+ * terminate fatals, apply mid-run controls, harden ops edges ([9171835](https://github.com/adammatthewsteinberger/codexloop/commit/91718359a07f5e25ffd1366c7ea8bbfba51b0a01))
75
+ * treat ControlCommand as the inbox union and wrap parse errors ([0885204](https://github.com/adammatthewsteinberger/codexloop/commit/08852040d2a48a14eb5b7b750fa5d02bb9314e4b))
76
+ * unstick version CI and keep TestPyPI on develop ([a4cf78e](https://github.com/adammatthewsteinberger/codexloop/commit/a4cf78eb32a622af03f707a5654c8da708a81f83))
77
+ * version CI + TestPyPI only from develop ([01d7695](https://github.com/adammatthewsteinberger/codexloop/commit/01d7695de87849b949ffd6e275b1f79126f9f2c6))
78
+
79
+
80
+ ### Documentation
81
+
82
+ * deploy MkDocs site to GitHub Pages ([bce3384](https://github.com/adammatthewsteinberger/codexloop/commit/bce33843a1eb7f2579fea6d895b9966abcf5f11e))
83
+ * GitHub Pages MkDocs site ([e1c286b](https://github.com/adammatthewsteinberger/codexloop/commit/e1c286bef14b63f5b337548eb99bad94b917f21a))
84
+
85
+ ## [0.1.1](https://github.com/adammatthewsteinberger/codexloop/compare/v0.1.0...v0.1.1) (2026-08-14)
86
+
87
+
88
+ ### Bug Fixes
89
+
90
+ * pin release-please to main ([4c974a2](https://github.com/adammatthewsteinberger/codexloop/commit/4c974a243f98d0790325929fd124c4aca72f04f7))
91
+ * pin release-please to main and Node 24 action ([cf19789](https://github.com/adammatthewsteinberger/codexloop/commit/cf19789c9ed4fc179f88ef6176f8b05859d05cb8))
92
+ * unstick version CI and keep TestPyPI on develop ([a4cf78e](https://github.com/adammatthewsteinberger/codexloop/commit/a4cf78eb32a622af03f707a5654c8da708a81f83))
93
+ * version CI + TestPyPI only from develop ([01d7695](https://github.com/adammatthewsteinberger/codexloop/commit/01d7695de87849b949ffd6e275b1f79126f9f2c6))
94
+
95
+
96
+ ### Documentation
97
+
98
+ * deploy MkDocs site to GitHub Pages ([bce3384](https://github.com/adammatthewsteinberger/codexloop/commit/bce33843a1eb7f2579fea6d895b9966abcf5f11e))
99
+ * GitHub Pages MkDocs site ([e1c286b](https://github.com/adammatthewsteinberger/codexloop/commit/e1c286bef14b63f5b337548eb99bad94b917f21a))
100
+
101
+ ## 0.1.0 (2026-08-13)
102
+
103
+
104
+ ### Features
105
+
106
+ * add app-server rate-limit probe client ([a30ef93](https://github.com/adammatthewsteinberger/codexloop/commit/a30ef9377685ef9aea8f5096e1759b0f6293574e))
107
+ * add application ports and fakes ([33e721d](https://github.com/adammatthewsteinberger/codexloop/commit/33e721d0dab21b38c614ab71ea7c3e47a8126fb3))
108
+ * add autonomous runner and run/resume use cases ([bd36f45](https://github.com/adammatthewsteinberger/codexloop/commit/bd36f457548c5969f0fd37453c2d1ab5727d3302))
109
+ * add backoff and adaptive wait policy ([43c70c6](https://github.com/adammatthewsteinberger/codexloop/commit/43c70c68396255e10c61907497c53dd0d1c2ba63))
110
+ * add bootstrap and core CLI commands ([6b6aafc](https://github.com/adammatthewsteinberger/codexloop/commit/6b6aafc94f8d2513282389f154682b1b5a97bcee))
111
+ * add capacity value objects ([1aa3fed](https://github.com/adammatthewsteinberger/codexloop/commit/1aa3fede743d6c5db518f869d03826788c64da5b))
112
+ * add clock, logging, config, rundir, state, and lock adapters ([8f7e4ad](https://github.com/adammatthewsteinberger/codexloop/commit/8f7e4ad1aad0f9a754e7ff5777898bfe5a35c5cd))
113
+ * add codex argv builder ([42ab842](https://github.com/adammatthewsteinberger/codexloop/commit/42ab8426e676b0c6b59bb655bfc94e4a607338ba))
114
+ * add control plane, savepoints, and ops CLI ([512e03f](https://github.com/adammatthewsteinberger/codexloop/commit/512e03f24eddf226425326b992eacc4732f1bc7b))
115
+ * add ephemeral read-only exec capacity probe ([427620b](https://github.com/adammatthewsteinberger/codexloop/commit/427620bda645389caf571bcef010d269d3457093))
116
+ * add error hierarchy and OpenAI error-code taxonomy ([1bf5aa2](https://github.com/adammatthewsteinberger/codexloop/commit/1bf5aa2f2805c80aeba0f37fbe6da1dcb4a59585))
117
+ * add generated OpenAI REST CLI surface with drift gate ([53320f8](https://github.com/adammatthewsteinberger/codexloop/commit/53320f82512869b43075d6eeaf3f6fe73a06a3dd))
118
+ * add optional app-server gateway, stream UI, docs, and release scaffolding ([23bfddf](https://github.com/adammatthewsteinberger/codexloop/commit/23bfddfb169cfb37e8fe60a9a80bd7f9b644bba9))
119
+ * add plan, budget, session, profile, approval, and control types ([07a8188](https://github.com/adammatthewsteinberger/codexloop/commit/07a8188207fa6fbac5f85114d891b266b6be1bf9))
120
+ * add read-only CODEX_HOME rollout tail ([071d6ab](https://github.com/adammatthewsteinberger/codexloop/commit/071d6abe526935893d7d330909e96a308e5203b2))
121
+ * add run-loop state machine ([582144f](https://github.com/adammatthewsteinberger/codexloop/commit/582144fcd2b5d3c327f6af36c74307a9a8818966))
122
+ * add scripted system harness and test-agent gate ([68a7ebf](https://github.com/adammatthewsteinberger/codexloop/commit/68a7ebf9483013f5e7fae4ff98ff2b0f5da843f0))
123
+ * add three-layer completion evaluation ([eee2cc3](https://github.com/adammatthewsteinberger/codexloop/commit/eee2cc3a70562126c438e1a1ba842abca9aa0db6))
124
+ * classify turn signals into capacity states ([f7c4162](https://github.com/adammatthewsteinberger/codexloop/commit/f7c4162048b62f83a7b7ea3f99474605f18376ef))
125
+ * implement codexloop M1–M5 (onion runner + REST + docs) ([1dbef91](https://github.com/adammatthewsteinberger/codexloop/commit/1dbef9118097d8b8210f6a770df8c4c05956f6ce))
126
+ * parse codex exec JSONL events ([1cdc76c](https://github.com/adammatthewsteinberger/codexloop/commit/1cdc76c754f0e0f023f7dc94472be59f9776d3f5))
127
+ * supervise codex subprocess with concurrent pumps ([1c95f6e](https://github.com/adammatthewsteinberger/codexloop/commit/1c95f6e6fe628daefe0256e5ba5fb921bfd595a5))
128
+ * translate JSONL and drive codex exec gateway ([6a1842c](https://github.com/adammatthewsteinberger/codexloop/commit/6a1842c3bab3b9eb57d052b2bb8f1c45b919b69f))
129
+ * wire composite capacity probe and adaptive wait loop ([ab682b1](https://github.com/adammatthewsteinberger/codexloop/commit/ab682b16130829e3ae7a523597213c33509dec22))
130
+
131
+
132
+ ### Bug Fixes
133
+
134
+ * jitter throttle waits above Retry-After ([666a4e6](https://github.com/adammatthewsteinberger/codexloop/commit/666a4e6c3d73f277946e866d33866091c225e1c8))
135
+ * only break session locks for known-dead pids ([712b0f4](https://github.com/adammatthewsteinberger/codexloop/commit/712b0f4a4b25d83ba27c0ca53d8278e6961efbd9))
136
+ * preserve remaining work across capacity-rejected turns ([d2d10c3](https://github.com/adammatthewsteinberger/codexloop/commit/d2d10c36a93084a36f48509433d9bb6865172fde))
137
+ * seal onion contracts and order drain before signals ([cecf827](https://github.com/adammatthewsteinberger/codexloop/commit/cecf827e841d11df0fb34c71724415970da3ab7d))
138
+ * stabilize CI help and process-group cancel tests ([3fe2c6d](https://github.com/adammatthewsteinberger/codexloop/commit/3fe2c6d09f94adb0de528a74364a0d9d177ee77b))
139
+ * terminate fatals, apply mid-run controls, harden ops edges ([9171835](https://github.com/adammatthewsteinberger/codexloop/commit/91718359a07f5e25ffd1366c7ea8bbfba51b0a01))
140
+ * treat ControlCommand as the inbox union and wrap parse errors ([0885204](https://github.com/adammatthewsteinberger/codexloop/commit/08852040d2a48a14eb5b7b750fa5d02bb9314e4b))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: codexloop
3
- Version: 0.1.0
3
+ Version: 0.3.0
4
4
  Summary: Onion-architected, autonomous OpenAI Codex session runner — never blocks on a human, distinguishes rate limits from exhausted credits, and resumes safely across usage windows.
5
5
  Project-URL: Homepage, https://github.com/adammatthewsteinberger/codexloop
6
6
  Project-URL: Repository, https://github.com/adammatthewsteinberger/codexloop
@@ -56,18 +56,26 @@ Autonomous OpenAI Codex / GPT session runner. Same job as
56
56
  a human, and never treat `insufficient_quota` / billing as a waitable
57
57
  `rate_limit_exceeded` window.
58
58
 
59
- **Status:** M1–M5 implemented on `feat/m1-pure-core` (onion core, exec gateway,
60
- capacity probes, control plane, generated REST CLI, optional app-server transport
61
- with exec fallback). MIT-licensed; author Adam Matthew Steinberger.
59
+ **Docs:** https://adammatthewsteinberger.github.io/codexloop/
60
+
61
+ **Status:** M1–M5 on PyPI (`0.1.0`) onion core, exec gateway, capacity probes,
62
+ control plane, generated REST CLI, optional app-server transport with exec
63
+ fallback. MIT-licensed; author Adam Matthew Steinberger.
62
64
 
63
65
  ## Install
64
66
 
65
67
  ```bash
66
- pip install -e ".[dev]"
68
+ pip install codexloop
67
69
  codexloop --version
68
70
  codexloop doctor
69
71
  ```
70
72
 
73
+ For local development:
74
+
75
+ ```bash
76
+ pip install -e ".[dev]"
77
+ ```
78
+
71
79
  ## Quick start
72
80
 
73
81
  ```bash
@@ -5,18 +5,26 @@ Autonomous OpenAI Codex / GPT session runner. Same job as
5
5
  a human, and never treat `insufficient_quota` / billing as a waitable
6
6
  `rate_limit_exceeded` window.
7
7
 
8
- **Status:** M1–M5 implemented on `feat/m1-pure-core` (onion core, exec gateway,
9
- capacity probes, control plane, generated REST CLI, optional app-server transport
10
- with exec fallback). MIT-licensed; author Adam Matthew Steinberger.
8
+ **Docs:** https://adammatthewsteinberger.github.io/codexloop/
9
+
10
+ **Status:** M1–M5 on PyPI (`0.1.0`) onion core, exec gateway, capacity probes,
11
+ control plane, generated REST CLI, optional app-server transport with exec
12
+ fallback. MIT-licensed; author Adam Matthew Steinberger.
11
13
 
12
14
  ## Install
13
15
 
14
16
  ```bash
15
- pip install -e ".[dev]"
17
+ pip install codexloop
16
18
  codexloop --version
17
19
  codexloop doctor
18
20
  ```
19
21
 
22
+ For local development:
23
+
24
+ ```bash
25
+ pip install -e ".[dev]"
26
+ ```
27
+
20
28
  ## Quick start
21
29
 
22
30
  ```bash
@@ -0,0 +1,74 @@
1
+ # Publishing
2
+
3
+ `codexloop` ships via [Trusted Publishing](https://docs.pypi.org/trusted-publishers/)
4
+ (OIDC). No long-lived PyPI API tokens are stored in GitHub.
5
+
6
+ ## Environments
7
+
8
+ | GitHub Environment | Index | Branch / workflow |
9
+ |---|---|---|
10
+ | `testpypi` | https://test.pypi.org | **`develop`** → `.github/workflows/publish-testpypi.yml` |
11
+ | `pypi` | https://pypi.org | **`main`** → `.github/workflows/release-please.yml` (`publish-pypi`) |
12
+
13
+ Create them once (repo **Settings → Environments**), or via API as in the
14
+ setup checklist below.
15
+
16
+ ## One-time Trusted Publisher setup
17
+
18
+ Do this **before** the first upload (pending publisher), signed in as the PyPI
19
+ owner account.
20
+
21
+ ### TestPyPI
22
+
23
+ 1. Open https://test.pypi.org/manage/account/publishing/
24
+ 2. Add a pending publisher:
25
+ - **PyPI Project Name:** `codexloop`
26
+ - **Owner:** `adammatthewsteinberger`
27
+ - **Repository name:** `codexloop`
28
+ - **Workflow name:** `publish-testpypi.yml`
29
+ - **Environment name:** `testpypi`
30
+
31
+ ### PyPI
32
+
33
+ 1. Open https://pypi.org/manage/account/publishing/
34
+ 2. Add a pending publisher:
35
+ - **PyPI Project Name:** `codexloop`
36
+ - **Owner:** `adammatthewsteinberger`
37
+ - **Repository name:** `codexloop`
38
+ - **Workflow name:** `release-please.yml`
39
+ - **Environment name:** `pypi`
40
+
41
+ ## Release flow
42
+
43
+ ```text
44
+ feat/* ──PR──► develop ──auto TestPyPI──► main ──release-please──► PyPI
45
+ ```
46
+
47
+ 1. Land work on `develop`. Every push to `develop` runs **Publish TestPyPI**
48
+ (`publish-testpypi.yml`). Do not publish TestPyPI from `main`.
49
+ 2. Smoke-install from TestPyPI if needed:
50
+ `pip install -i https://test.pypi.org/simple/ --pre codexloop`.
51
+ 3. Merge `develop` → `main` when ready.
52
+ 4. `release-please` opens a release PR against **`main` only**
53
+ (`target-branch: main` in `.github/workflows/release-please.yml`).
54
+ 5. Squash-merge the release PR → GitHub Release + tag → `publish-pypi`
55
+ uploads to **PyPI**. Do not open or merge `chore(develop): release …` PRs.
56
+
57
+ Manual PyPI retry (Trusted Publishing, `main` / tagged release only):
58
+
59
+ ```bash
60
+ gh workflow run release-please.yml -f publish_to_pypi=true
61
+ ```
62
+
63
+ Manual TestPyPI from `develop`:
64
+
65
+ ```bash
66
+ gh workflow run "Publish TestPyPI" --ref develop
67
+ ```
68
+
69
+ ## Local dry-run (no upload)
70
+
71
+ ```bash
72
+ python -m build
73
+ twine check --strict dist/*
74
+ ```
@@ -0,0 +1,44 @@
1
+ site_name: codexloop
2
+ site_description: Autonomous OpenAI Codex session runner
3
+ site_url: https://adammatthewsteinberger.github.io/codexloop/
4
+ repo_url: https://github.com/adammatthewsteinberger/codexloop
5
+ repo_name: adammatthewsteinberger/codexloop
6
+ theme:
7
+ name: material
8
+ features:
9
+ - navigation.sections
10
+ - content.code.copy
11
+ markdown_extensions:
12
+ - admonition
13
+ - pymdownx.details
14
+ - pymdownx.superfences
15
+ - toc:
16
+ permalink: true
17
+ exclude_docs: |
18
+ plans/**
19
+ superpowers/**
20
+ nav:
21
+ - Home: index.md
22
+ - Getting started: getting-started.md
23
+ - Guides:
24
+ - REST API surface: guides/rest-api-surface.md
25
+ - Architecture:
26
+ - Overview: architecture/index.md
27
+ - ADRs:
28
+ - Index: architecture/adr/index.md
29
+ - "0001 Onion import-linter": architecture/adr/0001-onion-import-linter.md
30
+ - "0002 Subprocess codex exec": architecture/adr/0002-subprocess-codex-exec.md
31
+ - "0003 Credits exhausted": architecture/adr/0003-credits-exhausted.md
32
+ - "0004 Adaptive probe loop": architecture/adr/0004-adaptive-probe-loop.md
33
+ - "0005 Layered capacity probe": architecture/adr/0005-layered-capacity-probe.md
34
+ - "0006 Generated OpenAI REST": architecture/adr/0006-generated-openai-rest.md
35
+ - "0007 Default approval/sandbox": architecture/adr/0007-default-approval-sandbox.md
36
+ - "0008 Policy via -c flags": architecture/adr/0008-policy-via-c-flags.md
37
+ - "0009 Optional app-server": architecture/adr/0009-optional-app-server.md
38
+ - "0010 Rollout best-effort": architecture/adr/0010-rollout-best-effort.md
39
+ - "0011 Never consume resets": architecture/adr/0011-never-consume-resets.md
40
+ - "0012 Minimum Codex version": architecture/adr/0012-minimum-codex-version.md
41
+ - Reference: reference/cli.md
42
+ - Contributing: contributing.md
43
+ - Publishing: publishing.md
44
+ strict: true
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "codexloop"
7
- version = "0.1.0"
7
+ version = "0.3.0"
8
8
  description = "Onion-architected, autonomous OpenAI Codex session runner — never blocks on a human, distinguishes rate limits from exhausted credits, and resumes safely across usage windows."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -173,3 +173,16 @@ forbidden_modules = [
173
173
  "docker",
174
174
  "sqlalchemy",
175
175
  ]
176
+
177
+
178
+ [[tool.importlinter.contracts]]
179
+ name = "Interfaces declare seams, never consume them"
180
+ type = "forbidden"
181
+ source_modules = ["codexloop.application.interfaces"]
182
+ forbidden_modules = [
183
+ "codexloop.application.runner",
184
+ "codexloop.application.usecases",
185
+ "codexloop.infrastructure",
186
+ "codexloop.cli",
187
+ "codexloop.bootstrap",
188
+ ]
@@ -1,3 +1,3 @@
1
1
  """codexloop — onion-architected, autonomous OpenAI Codex session runner."""
2
2
 
3
- __version__ = "0.1.0"
3
+ __version__ = "0.3.0"
@@ -0,0 +1,75 @@
1
+ """Application interfaces -- every seam implemented by infrastructure/ and
2
+ never imported from it.
3
+
4
+ One module per collaborator family so a reader finds a seam by what it does
5
+ rather than by scrolling one long file. `application/ports.py` re-exports
6
+ this package unchanged, so existing imports keep working.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from codexloop.application.interfaces.agent import (
12
+ AgentGateway,
13
+ CapacityProbe,
14
+ RunResources,
15
+ ThreadCatalog,
16
+ )
17
+ from codexloop.application.interfaces.api import (
18
+ ApiGateway,
19
+ )
20
+ from codexloop.application.interfaces.control import (
21
+ ControlInbox,
22
+ RunControl,
23
+ )
24
+ from codexloop.application.interfaces.doctor import (
25
+ DoctorCheck,
26
+ DoctorEnvironment,
27
+ DoctorReport,
28
+ )
29
+ from codexloop.application.interfaces.observability import (
30
+ AuditLog,
31
+ Logger,
32
+ Notifier,
33
+ ProgressReporter,
34
+ RunEventSink,
35
+ StateBus,
36
+ )
37
+ from codexloop.application.interfaces.permissions import (
38
+ PermissionMode,
39
+ )
40
+ from codexloop.application.interfaces.storage import (
41
+ RunSnapshotSink,
42
+ RunStateStore,
43
+ SavePointStore,
44
+ SessionLock,
45
+ )
46
+ from codexloop.application.interfaces.system import (
47
+ Clock,
48
+ Sleeper,
49
+ )
50
+
51
+ __all__ = [
52
+ "AgentGateway",
53
+ "ApiGateway",
54
+ "AuditLog",
55
+ "CapacityProbe",
56
+ "Clock",
57
+ "ControlInbox",
58
+ "DoctorCheck",
59
+ "DoctorEnvironment",
60
+ "DoctorReport",
61
+ "Logger",
62
+ "Notifier",
63
+ "PermissionMode",
64
+ "ProgressReporter",
65
+ "RunControl",
66
+ "RunEventSink",
67
+ "RunResources",
68
+ "RunSnapshotSink",
69
+ "RunStateStore",
70
+ "SavePointStore",
71
+ "SessionLock",
72
+ "Sleeper",
73
+ "StateBus",
74
+ "ThreadCatalog",
75
+ ]
@@ -0,0 +1,46 @@
1
+ """The vendor session seam: sending turns, probing capacity, enumerating
2
+ sessions, and the run-scoped resources attached to one."""
3
+
4
+ from __future__ import annotations
5
+
6
+ from collections.abc import Mapping, Sequence
7
+ from typing import Protocol, runtime_checkable
8
+
9
+ from codexloop.application.dto import ProbeResult, TurnOutcome
10
+ from codexloop.application.interfaces.permissions import PermissionMode
11
+ from codexloop.domain.model_profile import ModelEffortProfile
12
+ from codexloop.domain.session import ThreadRef
13
+
14
+
15
+ @runtime_checkable
16
+ class AgentGateway(Protocol):
17
+ """Vendor-agnostic agent session (exec and app-server adapters implement this)."""
18
+
19
+ async def send_turn(self, prompt: str) -> TurnOutcome: ...
20
+ async def close(self) -> None: ...
21
+ async def set_profile(self, profile: ModelEffortProfile) -> None: ...
22
+ async def set_permission_mode(self, mode: PermissionMode) -> None: ...
23
+ async def set_cwd(self, path: str) -> None: ...
24
+ async def set_session_resources(self, resources: Mapping[str, object]) -> None: ...
25
+ def resolve_tool_approval(self, request_id: str, *, allow: bool, reason: str = "") -> bool: ...
26
+
27
+
28
+ @runtime_checkable
29
+ class CapacityProbe(Protocol):
30
+ async def probe(self) -> ProbeResult: ...
31
+
32
+
33
+ @runtime_checkable
34
+ class ThreadCatalog(Protocol):
35
+ """Our run registry keyed by ``thread_id``, not vendor session discovery."""
36
+
37
+ def list_threads(self) -> Sequence[ThreadRef]: ...
38
+ def get(self, thread_id: str) -> ThreadRef | None: ...
39
+ def record(self, ref: ThreadRef) -> None: ...
40
+
41
+
42
+ @runtime_checkable
43
+ class RunResources(Protocol):
44
+ """Placeholder for run-scoped attachments applied mid-run."""
45
+
46
+ def as_payload(self) -> Mapping[str, object]: ...