code-coordinator 0.5.318__tar.gz → 0.5.320__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 (820) hide show
  1. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/PKG-INFO +1 -1
  2. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/code_coordinator.egg-info/PKG-INFO +1 -1
  3. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/code_coordinator.egg-info/scm_version.json +2 -2
  4. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/portal.py +118 -2
  5. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/db.py +15 -1
  6. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/decomposition_chat.py +32 -4
  7. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/portal_store.py +219 -1
  8. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/serve_app.py +111 -0
  9. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_portal.py +166 -0
  10. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_coord_test_runner_populated_home.py +15 -0
  11. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_db.py +150 -0
  12. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_decomposition_chat.py +47 -0
  13. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_portal_store.py +304 -0
  14. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_sqlite_connect_ratchet.py +28 -4
  15. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/.claude/commands/board.md +0 -0
  16. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/.claude/commands/complete-session.md +0 -0
  17. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/.claude/commands/coordinator.md +0 -0
  18. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/.githooks/_lib.sh +0 -0
  19. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/.githooks/post-checkout +0 -0
  20. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/.githooks/post-commit +0 -0
  21. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/.githooks/post-merge +0 -0
  22. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  23. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/.github/coord-ci-acceptance.yml +0 -0
  24. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/.github/workflows/auto-release.yml +0 -0
  25. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/.github/workflows/publish.yml +0 -0
  26. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/.github/workflows/test.yml +0 -0
  27. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/.gitignore +0 -0
  28. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/CLAUDE.md +0 -0
  29. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/GOAL.md +0 -0
  30. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/LICENSE +0 -0
  31. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/MANIFEST.in +0 -0
  32. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/README.md +0 -0
  33. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/code_coordinator.egg-info/SOURCES.txt +0 -0
  34. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/code_coordinator.egg-info/dependency_links.txt +0 -0
  35. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/code_coordinator.egg-info/entry_points.txt +0 -0
  36. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/code_coordinator.egg-info/requires.txt +0 -0
  37. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/code_coordinator.egg-info/scm_file_list.json +0 -0
  38. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/code_coordinator.egg-info/top_level.txt +0 -0
  39. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/__init__.py +0 -0
  40. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/_board_mapping.py +0 -0
  41. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/acceptance.py +0 -0
  42. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/acceptance_drivers.py +0 -0
  43. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/agent.py +0 -0
  44. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/agent_app.py +0 -0
  45. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/agent_update.py +0 -0
  46. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/agents/opencode/.gitignore +0 -0
  47. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/agents/opencode/agents/work.md +0 -0
  48. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/agents/opencode/routing.jsonc +0 -0
  49. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/approved_work.py +0 -0
  50. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/audit.py +0 -0
  51. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/auto_loop.py +0 -0
  52. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/block_log.py +0 -0
  53. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/board_schema.py +0 -0
  54. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/board_service.py +0 -0
  55. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/board_wire.py +0 -0
  56. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/brain.py +0 -0
  57. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/branch_model.py +0 -0
  58. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/bug_intake.py +0 -0
  59. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/cargo_cache.py +0 -0
  60. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/ci_fix.py +0 -0
  61. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/ci_github.py +0 -0
  62. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/ci_gitlab.py +0 -0
  63. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/ci_store.py +0 -0
  64. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/claim.py +0 -0
  65. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/cli.py +0 -0
  66. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/client.py +0 -0
  67. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/__init__.py +0 -0
  68. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/_common.py +0 -0
  69. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/acceptance.py +0 -0
  70. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/agent_ops.py +0 -0
  71. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/audit.py +0 -0
  72. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/chat.py +0 -0
  73. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/dispatch.py +0 -0
  74. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/dispatch_workers.py +0 -0
  75. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/drive.py +0 -0
  76. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/drive_queue.py +0 -0
  77. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/gate_a.py +0 -0
  78. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/gates.py +0 -0
  79. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/issues.py +0 -0
  80. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/lifecycle.py +0 -0
  81. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/machine.py +0 -0
  82. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/merge.py +0 -0
  83. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/milestone.py +0 -0
  84. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/plan_followup.py +0 -0
  85. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/plans.py +0 -0
  86. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/pr.py +0 -0
  87. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/release.py +0 -0
  88. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/repo.py +0 -0
  89. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/report.py +0 -0
  90. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/review.py +0 -0
  91. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/scorecard.py +0 -0
  92. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/sessions.py +0 -0
  93. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/setup.py +0 -0
  94. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/status.py +0 -0
  95. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/store_migrate.py +0 -0
  96. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/terminal.py +0 -0
  97. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/test_gate.py +0 -0
  98. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/commands/tui.py +0 -0
  99. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/comments.py +0 -0
  100. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/config.py +0 -0
  101. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/config_reload.py +0 -0
  102. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/confirm_test.py +0 -0
  103. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/conflict_fix.py +0 -0
  104. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/dao.py +0 -0
  105. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/dashboard/__init__.py +0 -0
  106. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/dashboard/fixture.py +0 -0
  107. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/dashboard/index.html +0 -0
  108. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/dashboard/server.py +0 -0
  109. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/dashboard/terminal.py +0 -0
  110. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/dead_end.py +0 -0
  111. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/README.md +0 -0
  112. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/coord-agent.service +0 -0
  113. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/coord-db-backup.service +0 -0
  114. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/coord-db-backup.sh +0 -0
  115. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/coord-db-backup.timer +0 -0
  116. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/coord-drive-queue.service +0 -0
  117. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/coord-drive-queue.timer +0 -0
  118. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/coord-failure-notify.service +0 -0
  119. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/coord-fleet-watchdog.service +0 -0
  120. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/coord-fleet-watchdog.timer +0 -0
  121. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/coord-notify.service +0 -0
  122. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/coord-notify.timer +0 -0
  123. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/coord-release-propagate.service +0 -0
  124. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/coord-release-propagate.timer +0 -0
  125. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/coord-release-window.service +0 -0
  126. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/coord-release-window.timer +0 -0
  127. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/coord-serve.service +0 -0
  128. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/coord-web-dist-build.service +0 -0
  129. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/coord-web-dist-build.timer +0 -0
  130. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy/coord-web.service +0 -0
  131. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy_manifest.py +0 -0
  132. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deploy_units.py +0 -0
  133. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deprecation_telemetry.py +0 -0
  134. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/deps.py +0 -0
  135. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/diagnose.py +0 -0
  136. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/dispatch.py +0 -0
  137. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/dist_name.py +0 -0
  138. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/drive.py +0 -0
  139. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/drive_queue.py +0 -0
  140. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/drive_state.py +0 -0
  141. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/events.py +0 -0
  142. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/failure_class.py +0 -0
  143. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/filelock.py +0 -0
  144. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/fleet_config_health.py +0 -0
  145. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/forge_availability.py +0 -0
  146. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/freshness.py +0 -0
  147. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/gate_a.py +0 -0
  148. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/gate_b.py +0 -0
  149. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/gate_snapshot.py +0 -0
  150. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/gates.py +0 -0
  151. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/github_ops.py +0 -0
  152. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/github_throttle.py +0 -0
  153. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/goal.py +0 -0
  154. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/graph_health.py +0 -0
  155. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/__init__.py +0 -0
  156. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/aggregate.py +0 -0
  157. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/__init__.py +0 -0
  158. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/_ci_pin.py +0 -0
  159. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/agent_install.py +0 -0
  160. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/cargo_targets.py +0 -0
  161. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/claude_binary.py +0 -0
  162. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/coord_tui_ci_pin.py +0 -0
  163. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/coord_web_ci_pin.py +0 -0
  164. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/deploy_lane_facts.py +0 -0
  165. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/disk.py +0 -0
  166. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/fleet_board.py +0 -0
  167. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/fleet_deploy_lanes.py +0 -0
  168. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/fleet_phantom.py +0 -0
  169. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/fleet_unit_drift.py +0 -0
  170. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/graph.py +0 -0
  171. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/graphify_cli.py +0 -0
  172. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/index_lock.py +0 -0
  173. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/issues_sync_staleness.py +0 -0
  174. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/plan_usage.py +0 -0
  175. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/release_cordon.py +0 -0
  176. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/repo_state.py +0 -0
  177. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/spawned_coord.py +0 -0
  178. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/stalled_pipeline.py +0 -0
  179. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/timer_active.py +0 -0
  180. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/toolchain.py +0 -0
  181. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/unit_drift.py +0 -0
  182. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/unit_enablement.py +0 -0
  183. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/wedged_drive_queue.py +0 -0
  184. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/checks/worktrees.py +0 -0
  185. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/cli.py +0 -0
  186. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/context.py +0 -0
  187. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/fleet_snapshot.py +0 -0
  188. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/models.py +0 -0
  189. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/pypi.py +0 -0
  190. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/registry.py +0 -0
  191. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/render.py +0 -0
  192. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/health/units.py +0 -0
  193. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/hooks.py +0 -0
  194. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/housekeeping.py +0 -0
  195. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/interactive.py +0 -0
  196. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/issue_store.py +0 -0
  197. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/issues_sync_status.py +0 -0
  198. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/liveness_auditor.py +0 -0
  199. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/machine_onboard.py +0 -0
  200. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/machine_pause.py +0 -0
  201. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/merge_queue.py +0 -0
  202. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/milestone_chat.py +0 -0
  203. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/milestone_dispatch.py +0 -0
  204. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/milestone_gate.py +0 -0
  205. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/milestone_order.py +0 -0
  206. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/mock_author.py +0 -0
  207. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/models.py +0 -0
  208. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/network.py +0 -0
  209. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/new_issue_chat.py +0 -0
  210. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/notifier/__init__.py +0 -0
  211. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/notifier/baseline.py +0 -0
  212. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/notifier/cli.py +0 -0
  213. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/notifier/collect.py +0 -0
  214. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/notifier/digest.py +0 -0
  215. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/notifier/models.py +0 -0
  216. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/notifier/predicate.py +0 -0
  217. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/notifier/service.py +0 -0
  218. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/notifier/store.py +0 -0
  219. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/notifier/transport.py +0 -0
  220. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/notify.py +0 -0
  221. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/openapi.py +0 -0
  222. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/overlap_fence.py +0 -0
  223. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/overlap_predict.py +0 -0
  224. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/parentage.py +0 -0
  225. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/parentage_github.py +0 -0
  226. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/pipeline.py +0 -0
  227. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/plan_parser.py +0 -0
  228. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/plans.py +0 -0
  229. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/platform_paths.py +0 -0
  230. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/portal_bridge.py +0 -0
  231. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/portal_sync.py +0 -0
  232. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/pr_body_lint.py +0 -0
  233. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/prereqs.py +0 -0
  234. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/progress.py +0 -0
  235. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/providers/__init__.py +0 -0
  236. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/providers/base.py +0 -0
  237. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/providers/claude.py +0 -0
  238. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/providers/claude_pty.py +0 -0
  239. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/providers/opencode.py +0 -0
  240. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/queue_diagnose.py +0 -0
  241. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/reconcile.py +0 -0
  242. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/reconcile_tick.py +0 -0
  243. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/refine_chat.py +0 -0
  244. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/release_cordon.py +0 -0
  245. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/release_propagate.py +0 -0
  246. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/release_verify.py +0 -0
  247. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/release_window.py +0 -0
  248. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/repo_dormancy.py +0 -0
  249. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/repo_edit.py +0 -0
  250. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/repo_onboard.py +0 -0
  251. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/reports.py +0 -0
  252. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/rest_schema.py +0 -0
  253. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/revalidate.py +0 -0
  254. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/review.py +0 -0
  255. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/scorecard.py +0 -0
  256. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/self_health.py +0 -0
  257. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/skills/coord-dispatch-verbs/SKILL.md +0 -0
  258. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/skills/drive-queue-preflight/SKILL.md +0 -0
  259. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/skills/fleet-restart-safety/SKILL.md +0 -0
  260. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/skills/merge-stuck-triage/SKILL.md +0 -0
  261. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/skills/pipeline-limbo-triage/SKILL.md +0 -0
  262. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/skills/portal-followup/SKILL.md +0 -0
  263. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/skills/release-now/SKILL.md +0 -0
  264. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/skills/review-verdict-recovery/SKILL.md +0 -0
  265. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/skills/tui-quadraui-workflow/SKILL.md +0 -0
  266. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/skills/update-issue/SKILL.md +0 -0
  267. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/smoke.py +0 -0
  268. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/spend_ceiling.py +0 -0
  269. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/split_work.py +0 -0
  270. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/sql.py +0 -0
  271. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/stage_projection.py +0 -0
  272. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/state.py +0 -0
  273. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/store_migrate.py +0 -0
  274. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/test_author.py +0 -0
  275. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/test_chat.py +0 -0
  276. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/test_orchestrator.py +0 -0
  277. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/test_report.py +0 -0
  278. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/tui_release.py +0 -0
  279. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/usage.py +0 -0
  280. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/usage_limits.py +0 -0
  281. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/usage_rollup.py +0 -0
  282. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coord/worker_events.py +0 -0
  283. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/coordinator.example.yml +0 -0
  284. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-agent.service +0 -0
  285. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-db-backup.service +0 -0
  286. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-db-backup.sh +0 -0
  287. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-db-backup.timer +0 -0
  288. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-drive-queue.service +0 -0
  289. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-drive-queue.timer +0 -0
  290. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-failure-notify.service +0 -0
  291. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-failure-notify.sh +0 -0
  292. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-fleet-watchdog.service +0 -0
  293. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-fleet-watchdog.timer +0 -0
  294. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-notify.service +0 -0
  295. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-notify.timer +0 -0
  296. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-release-propagate.service +0 -0
  297. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-release-propagate.timer +0 -0
  298. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-release-window.service +0 -0
  299. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-release-window.timer +0 -0
  300. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-serve.service +0 -0
  301. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-web-dist-build.service +0 -0
  302. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-web-dist-build.sh +0 -0
  303. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-web-dist-build.timer +0 -0
  304. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-web-rollback.sh +0 -0
  305. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/coord-web.service +0 -0
  306. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/deploy/node-shim.sh +0 -0
  307. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/ADR_COORD_TUI_CI.md +0 -0
  308. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/ADR_COORD_WEB_ACCEPTANCE_SUITE.md +0 -0
  309. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/ADR_COORD_WEB_CI.md +0 -0
  310. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/ADR_COORD_WEB_DIST.md +0 -0
  311. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/ADR_PY_RUST_MIRRORS.md +0 -0
  312. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/AGENT_OPERATIONS.md +0 -0
  313. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/ARCHITECTURE.md +0 -0
  314. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/ARCH_SECURITY_GATES.md +0 -0
  315. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/COCKPIT.md +0 -0
  316. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/CONTROL_CENTER.md +0 -0
  317. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/COST_DISCIPLINE.md +0 -0
  318. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/CROSS_PLATFORM.md +0 -0
  319. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/CUSTOMER_FACING_APPS.md +0 -0
  320. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/CUSTOMER_PORTAL.md +0 -0
  321. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/DRIVE_QUEUE.md +0 -0
  322. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/EPHEMERAL_WORKERS.md +0 -0
  323. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/FORGE_MIGRATION.md +0 -0
  324. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/GRAPHIFY_SETUP.md +0 -0
  325. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/ISSUE_GUIDANCE.md +0 -0
  326. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/MAC_MINI.md +0 -0
  327. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/MERGE_AUTO_DRAIN_TRUST_BAR.md +0 -0
  328. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/NOTIFIER.md +0 -0
  329. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/OPENCODE_VERIFICATION.md +0 -0
  330. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/OPERATING_GOTCHAS.md +0 -0
  331. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/OPERATOR_GUIDES.md +0 -0
  332. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/ORACLE_LOOP.md +0 -0
  333. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/PHONE_WEBAPP.md +0 -0
  334. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/PIPELINE_V2.md +0 -0
  335. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/PLATFORM_EVOLUTION.md +0 -0
  336. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/SECOND_BACKEND.md +0 -0
  337. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/STORE_SERVICE.md +0 -0
  338. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/TEST_FIRST_BUG_LANE.md +0 -0
  339. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/WEB_CONTROL_CENTER.md +0 -0
  340. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/WSL_WINDOWS_WORKER.md +0 -0
  341. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/mocks/web/README.md +0 -0
  342. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/mocks/web/_tokens.css +0 -0
  343. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/mocks/web/issue-detail.html +0 -0
  344. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/mocks/web/pipeline-narrow.html +0 -0
  345. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/docs/mocks/web/pipeline-wide.html +0 -0
  346. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/graphify-out/.gitignore +0 -0
  347. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/install-agent.sh +0 -0
  348. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/pyproject.toml +0 -0
  349. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/audit_review_verdict_overrides.py +0 -0
  350. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/azure-workers/bootstrap-shared.sh +0 -0
  351. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/azure-workers/build-worker-image.sh +0 -0
  352. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/azure-workers/coordinator-machine.py +0 -0
  353. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/azure-workers/epic-down.sh +0 -0
  354. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/azure-workers/epic-up.sh +0 -0
  355. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/azure-workers/preflight.sh +0 -0
  356. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/azure-workers/provision-worker.sh +0 -0
  357. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/azure-workers/scrub-and-generalize.sh +0 -0
  358. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/azure-workers/tailnet-acl.hujson +0 -0
  359. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/azure-workers/verify-github-token.sh +0 -0
  360. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/check_gh_argv_containment.py +0 -0
  361. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/codegen.py +0 -0
  362. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/coord-test-runner.sh +0 -0
  363. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/coord-tui-scaffold/.github/coord-ci-acceptance.yml +0 -0
  364. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/coord-tui-scaffold/.github/workflows/cargo-test.yml +0 -0
  365. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/coord-tui-scaffold/.github/workflows/codegen-drift.yml +0 -0
  366. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/coord-tui-scaffold/CLAUDE.md +0 -0
  367. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/coord-venv-rollback.sh +0 -0
  368. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/drive-batch.sh +0 -0
  369. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/extract-coord-tui.sh +0 -0
  370. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/fleet_watchdog.py +0 -0
  371. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/gen_board_fixture.py +0 -0
  372. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/gen_mock_index.py +0 -0
  373. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/next_release_tag.py +0 -0
  374. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/run_tests_in_populated_home.sh +0 -0
  375. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/run_tests_without_gh.sh +0 -0
  376. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/smoke_437_interactive.py +0 -0
  377. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/verify_878_review_capture.py +0 -0
  378. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/verify_release_published.py +0 -0
  379. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/scripts/verify_release_wheel.py +0 -0
  380. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/setup.cfg +0 -0
  381. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/SMOKE_SET.md +0 -0
  382. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/__init__.py +0 -0
  383. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/acceptance/ms-37/conftest.py +0 -0
  384. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/acceptance/ms-37/contract.md +0 -0
  385. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/acceptance/ms-37/manifest.yml +0 -0
  386. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/acceptance/ms-37/test_usage_cli_1115.py +0 -0
  387. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/acceptance/ms-37/test_usage_core_1118.py +0 -0
  388. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/acceptance/ms-51/contract.md +0 -0
  389. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/acceptance/ms-51/home-active-extended.spec.ts +0 -0
  390. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/acceptance/ms-51/home-active.spec.ts +0 -0
  391. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/acceptance/ms-51/manifest.yml +0 -0
  392. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/acceptance/ms-51/mocks/home-active.html +0 -0
  393. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/acceptance/ms-51/tsconfig.json +0 -0
  394. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/acceptance/ms-example/mocks/home-active.html +0 -0
  395. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/backends.py +0 -0
  396. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/conftest.py +0 -0
  397. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/board-pipeline-basic.json +0 -0
  398. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/board-pipeline-terminal-gates.json +0 -0
  399. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/opencode_run_failure_sample.jsonl +0 -0
  400. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/opencode_run_length_sample.jsonl +0 -0
  401. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/opencode_run_sample.jsonl +0 -0
  402. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/playwright/all_pass.json +0 -0
  403. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/playwright/global_setup_crash.json +0 -0
  404. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/playwright/mixed_fail.json +0 -0
  405. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/playwright/retry_then_pass.json +0 -0
  406. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/playwright/retry_then_pass.junit.xml +0 -0
  407. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/playwright/skip.json +0 -0
  408. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/playwright/truncated.json +0 -0
  409. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/test_report/cargo_compile_error.txt +0 -0
  410. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/test_report/cargo_multi_target_failures.txt +0 -0
  411. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/test_report/cargo_no_parseable_failures.txt +0 -0
  412. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/test_report/pytest_collection_error.txt +0 -0
  413. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/test_report/pytest_error_string_in_body.txt +0 -0
  414. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/test_report/pytest_internal_error.txt +0 -0
  415. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/test_report/pytest_mixed_failures.txt +0 -0
  416. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/fixtures/test_report/pytest_no_parseable_failures.txt +0 -0
  417. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_acceptance.py +0 -0
  418. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_acceptance_drivers.py +0 -0
  419. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent.py +0 -0
  420. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_api_error.py +0 -0
  421. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_app.py +0 -0
  422. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_branch_base.py +0 -0
  423. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_branch_capture.py +0 -0
  424. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_config_free_1712.py +0 -0
  425. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_deploy_units_endpoint.py +0 -0
  426. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_dirty_worktree.py +0 -0
  427. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_drive_queue_reconcile_2373.py +0 -0
  428. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_graph_self_heal.py +0 -0
  429. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_health_h3.py +0 -0
  430. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_idle_restart.py +0 -0
  431. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_push_failure.py +0 -0
  432. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_reap.py +0 -0
  433. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_repos_and_pull.py +0 -0
  434. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_restart_services_endpoint.py +0 -0
  435. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_skills_self_heal.py +0 -0
  436. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_startup_diagnostics.py +0 -0
  437. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_update.py +0 -0
  438. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_update_bluegreen.py +0 -0
  439. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_usage_limit.py +0 -0
  440. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_agent_zero_commit.py +0 -0
  441. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_ambient_home_isolation.py +0 -0
  442. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_approve_dependency_busy_2804.py +0 -0
  443. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_approve_reject_plan.py +0 -0
  444. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_approve_usage_gate.py +0 -0
  445. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_approved_work_2532.py +0 -0
  446. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_assignment_already_recorded_daemon.py +0 -0
  447. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_audit_log.py +0 -0
  448. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_audit_outcome.py +0 -0
  449. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_audit_query.py +0 -0
  450. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_auto_loop.py +0 -0
  451. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_auto_release_publish_2035.py +0 -0
  452. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_backend_selection.py +0 -0
  453. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_base_checkout_restore.py +0 -0
  454. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_block_log.py +0 -0
  455. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_board_cap_762.py +0 -0
  456. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_board_fixture.py +0 -0
  457. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_board_read_path.py +0 -0
  458. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_board_schema.py +0 -0
  459. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_board_service.py +0 -0
  460. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_board_state.py +0 -0
  461. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_board_wire.py +0 -0
  462. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_brain.py +0 -0
  463. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_branch_model.py +0 -0
  464. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_bug_intake.py +0 -0
  465. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_build_worker_image_env_update.py +0 -0
  466. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cargo_cache.py +0 -0
  467. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_check_gh_argv_containment.py +0 -0
  468. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_ci_acceptance_gate_1950.py +0 -0
  469. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_ci_fix.py +0 -0
  470. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_ci_gitlab.py +0 -0
  471. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_ci_parity_2091.py +0 -0
  472. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_ci_store.py +0 -0
  473. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_claim.py +0 -0
  474. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_claude_md_budget.py +0 -0
  475. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_acceptance.py +0 -0
  476. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_assign.py +0 -0
  477. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_assign_interactive_oracle_gate.py +0 -0
  478. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_assign_interactive_remote.py +0 -0
  479. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_assign_provider.py +0 -0
  480. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_assign_repo_drift_2219.py +0 -0
  481. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_audit.py +0 -0
  482. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_chat_continue.py +0 -0
  483. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_decide.py +0 -0
  484. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_diagnose_capability_rules.py +0 -0
  485. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_diagnose_config_provenance.py +0 -0
  486. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_diagnose_forge_availability.py +0 -0
  487. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_diagnose_graph.py +0 -0
  488. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_diagnose_self.py +0 -0
  489. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_diagnose_test_coverage.py +0 -0
  490. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_doctor.py +0 -0
  491. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_doctor_config_free_1801.py +0 -0
  492. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_doctor_config_mismatch_1712.py +0 -0
  493. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_drive.py +0 -0
  494. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_drive_queue.py +0 -0
  495. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_escalate.py +0 -0
  496. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_fix_headless_review.py +0 -0
  497. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_gate_a.py +0 -0
  498. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_install_drift.py +0 -0
  499. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_install_skills.py +0 -0
  500. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_issue_comment.py +0 -0
  501. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_issue_create_label.py +0 -0
  502. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_issue_reopen.py +0 -0
  503. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_issue_view_list.py +0 -0
  504. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_merge.py +0 -0
  505. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_milestone_assign.py +0 -0
  506. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_milestone_capture.py +0 -0
  507. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_milestone_chat_add_child.py +0 -0
  508. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_milestone_dispatch.py +0 -0
  509. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_milestone_gate_b.py +0 -0
  510. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_milestone_gate_c.py +0 -0
  511. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_milestone_order.py +0 -0
  512. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_milestone_remove_and_issue_close.py +0 -0
  513. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_milestone_ship.py +0 -0
  514. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_network.py +0 -0
  515. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_new_issue_chat.py +0 -0
  516. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_plans.py +0 -0
  517. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_pr.py +0 -0
  518. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_pull_artifact.py +0 -0
  519. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_queue.py +0 -0
  520. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_reattach_sessions.py +0 -0
  521. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_refine_board.py +0 -0
  522. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_release_preflight.py +0 -0
  523. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_release_propagate.py +0 -0
  524. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_release_window.py +0 -0
  525. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_repo_2220.py +0 -0
  526. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_review_test_author_tracking_epic_2639.py +0 -0
  527. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_scorecard.py +0 -0
  528. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_set_review_findings.py +0 -0
  529. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_status_advisory_terminal.py +0 -0
  530. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_status_contested_tag.py +0 -0
  531. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_status_merge_queue.py +0 -0
  532. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_status_provider.py +0 -0
  533. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_status_review_finalizing.py +0 -0
  534. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_status_test_failed_tag.py +0 -0
  535. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_status_usage_limit.py +0 -0
  536. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_sync_comments_873.py +0 -0
  537. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_test_plan.py +0 -0
  538. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_track.py +0 -0
  539. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_tui_update.py +0 -0
  540. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cli_wait.py +0 -0
  541. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_client_base_install.py +0 -0
  542. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_client_resource_migration_1946.py +0 -0
  543. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_commands_common.py +0 -0
  544. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_comments.py +0 -0
  545. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_completion_summary.py +0 -0
  546. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_config.py +0 -0
  547. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_config_acceptance.py +0 -0
  548. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_config_audit.py +0 -0
  549. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_config_pricing.py +0 -0
  550. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_config_snapshot_noncanonical_2208.py +0 -0
  551. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_config_usage_gate.py +0 -0
  552. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_confirm_test.py +0 -0
  553. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_conflict_fix.py +0 -0
  554. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_conflict_fix_semantic.py +0 -0
  555. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_coord_log_daemon_fallback_2547.py +0 -0
  556. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_coord_test.py +0 -0
  557. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_coord_test_runner_acceptance_toolchain_2936.py +0 -0
  558. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_coord_test_runner_baseline.py +0 -0
  559. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_coord_test_runner_routing.py +0 -0
  560. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_coord_test_runner_toolchain.py +0 -0
  561. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_coord_uat.py +0 -0
  562. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_coord_web_sse_restart_live.py +0 -0
  563. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_coordinator_machine.py +0 -0
  564. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_cross_platform_imports.py +0 -0
  565. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_dao.py +0 -0
  566. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_dashboard.py +0 -0
  567. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_dashboard_fixture.py +0 -0
  568. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_dashboard_terminal.py +0 -0
  569. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_dashboard_terminal_live.py +0 -0
  570. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_dead_end.py +0 -0
  571. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_deploy_coord_db_backup.py +0 -0
  572. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_deploy_coord_web_dist.py +0 -0
  573. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_deploy_coord_web_rollback.py +0 -0
  574. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_deploy_drive_queue_unit.py +0 -0
  575. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_deploy_failure_notify_unit.py +0 -0
  576. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_deploy_manifest.py +0 -0
  577. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_deploy_notify_unit.py +0 -0
  578. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_deploy_units_lane.py +0 -0
  579. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_deploy_web_unit.py +0 -0
  580. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_deprecation_telemetry.py +0 -0
  581. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_deps.py +0 -0
  582. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_diagnose.py +0 -0
  583. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_dispatch.py +0 -0
  584. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_dispatch_target_validation.py +0 -0
  585. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_dist_name.py +0 -0
  586. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_done_housekeeping.py +0 -0
  587. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_drive.py +0 -0
  588. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_drive_queue.py +0 -0
  589. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_drive_queue_blocked_rendering.py +0 -0
  590. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_drive_queue_launch_argv.py +0 -0
  591. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_drive_queue_max_parallel_per_repo_config.py +0 -0
  592. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_drive_queue_roll_pending.py +0 -0
  593. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_drive_queue_self_cordon_escalation.py +0 -0
  594. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_drive_state.py +0 -0
  595. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_drive_tmux.py +0 -0
  596. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_epic_up_capability_detection.py +0 -0
  597. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_epic_up_down_symlinked_config_1887.py +0 -0
  598. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_epic_up_image_provenance.py +0 -0
  599. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_errors.py +0 -0
  600. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_events.py +0 -0
  601. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_failure_class.py +0 -0
  602. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_filelock.py +0 -0
  603. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_finalize_interactive_exit_test_verdict.py +0 -0
  604. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_fix_of_force_override.py +0 -0
  605. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_fleet_config_health.py +0 -0
  606. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_fleet_health_probes.py +0 -0
  607. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_fleet_health_snapshot.py +0 -0
  608. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_fleet_watchdog.py +0 -0
  609. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_forge_availability.py +0 -0
  610. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_freshness.py +0 -0
  611. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_gate_a.py +0 -0
  612. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_gate_b.py +0 -0
  613. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_gate_snapshot_staleness.py +0 -0
  614. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_gates.py +0 -0
  615. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_gather_fleet_tmux_sessions.py +0 -0
  616. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_gen_mock_index.py +0 -0
  617. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_generated_rust_fixture.py +0 -0
  618. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_generated_rust_requests.py +0 -0
  619. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_generated_types_fixture.py +0 -0
  620. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_github_ops.py +0 -0
  621. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_github_throttle.py +0 -0
  622. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_goal.py +0 -0
  623. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_graph_health.py +0 -0
  624. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_graph_selfheal_absent_2237.py +0 -0
  625. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_handoff.py +0 -0
  626. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_health_checks.py +0 -0
  627. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_health_cli.py +0 -0
  628. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_health_cli_graph.py +0 -0
  629. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_health_config.py +0 -0
  630. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_health_context.py +0 -0
  631. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_health_coord_tui_ci_pin.py +0 -0
  632. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_health_coord_web_ci_pin.py +0 -0
  633. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_health_deploy_lane_facts.py +0 -0
  634. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_health_fix.py +0 -0
  635. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_health_incident_regression.py +0 -0
  636. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_health_issues_sync_staleness.py +0 -0
  637. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_health_pypi.py +0 -0
  638. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_health_registry.py +0 -0
  639. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_health_release_cordon_probe.py +0 -0
  640. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_health_timer_active.py +0 -0
  641. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_health_toolchain.py +0 -0
  642. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_health_unit_drift.py +0 -0
  643. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_health_unit_enablement.py +0 -0
  644. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_health_wedged_drive_queue.py +0 -0
  645. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_hooks.py +0 -0
  646. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_human_attended_437.py +0 -0
  647. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_init.py +0 -0
  648. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_install_agent_venv_2911.py +0 -0
  649. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_integration.py +0 -0
  650. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_interactive_briefing_echo.py +0 -0
  651. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_interactive_pane_log_2541.py +0 -0
  652. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_interactive_prefill_state.py +0 -0
  653. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_interactive_session_relaunch.py +0 -0
  654. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_interactive_test_verdict_backstop.py +0 -0
  655. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_interactive_token_attribution.py +0 -0
  656. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_interactive_worktree.py +0 -0
  657. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_issue_store_seam.py +0 -0
  658. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_issues_sync_status.py +0 -0
  659. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_liveness_auditor.py +0 -0
  660. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_liveness_notify.py +0 -0
  661. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_lock_contention_ratchet.py +0 -0
  662. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_machine_onboard.py +0 -0
  663. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_machine_pause.py +0 -0
  664. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_merge_queue.py +0 -0
  665. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_merge_verify.py +0 -0
  666. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_milestone_chat.py +0 -0
  667. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_milestone_dispatch.py +0 -0
  668. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_milestone_gate.py +0 -0
  669. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_milestone_order.py +0 -0
  670. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_milestone_seam.py +0 -0
  671. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_mock_author.py +0 -0
  672. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_model_tiering.py +0 -0
  673. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_models.py +0 -0
  674. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_models_config_labels.py +0 -0
  675. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_needs_attention.py +0 -0
  676. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_network.py +0 -0
  677. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_new_issue_chat.py +0 -0
  678. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_next_release_tag.py +0 -0
  679. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_node_shim.py +0 -0
  680. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_notifier_baseline.py +0 -0
  681. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_notifier_cli.py +0 -0
  682. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_notifier_collect.py +0 -0
  683. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_notifier_config.py +0 -0
  684. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_notifier_drive_seam.py +0 -0
  685. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_notifier_isolation.py +0 -0
  686. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_notifier_predicate.py +0 -0
  687. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_notifier_quiet_hours.py +0 -0
  688. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_notifier_service.py +0 -0
  689. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_notify.py +0 -0
  690. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_notify_drain.py +0 -0
  691. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_openapi.py +0 -0
  692. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_operational_defaults.py +0 -0
  693. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_overlap_fence.py +0 -0
  694. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_overlap_predict.py +0 -0
  695. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_packaged_deploy_units.py +0 -0
  696. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_parentage.py +0 -0
  697. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_paste_landed.py +0 -0
  698. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_phantom_heal_venv_independence_2570.py +0 -0
  699. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_pipeline.py +0 -0
  700. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_plan_followup_approve_plan_command.py +0 -0
  701. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_plan_followup_pr_command.py +0 -0
  702. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_plan_followup_review_command.py +0 -0
  703. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_plan_only.py +0 -0
  704. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_plan_parser.py +0 -0
  705. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_platform_paths.py +0 -0
  706. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_portal_bridge.py +0 -0
  707. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_portal_config.py +0 -0
  708. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_portal_sync.py +0 -0
  709. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_pr_body_lint.py +0 -0
  710. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_prereqs.py +0 -0
  711. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_production_db_guard.py +0 -0
  712. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_progress.py +0 -0
  713. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_provider_seam.py +0 -0
  714. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_providers.py +0 -0
  715. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_providers_config_labels.py +0 -0
  716. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_providers_pty.py +0 -0
  717. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_py_rust_mirror_inventory.py +0 -0
  718. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_quiet_hours.py +0 -0
  719. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_quiet_hours_store_2146.py +0 -0
  720. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_reap_merged_sessions.py +0 -0
  721. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_reap_stale_interactive_tick.py +0 -0
  722. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_reconcile.py +0 -0
  723. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_reconcile_branch.py +0 -0
  724. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_reconcile_completions.py +0 -0
  725. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_reconcile_late_agent_reports_2547.py +0 -0
  726. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_reconcile_merges.py +0 -0
  727. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_reconcile_no_agent_record.py +0 -0
  728. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_reconcile_tick.py +0 -0
  729. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_reconcile_usage_limit_done.py +0 -0
  730. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_refine_chat.py +0 -0
  731. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_release_cordon_2101.py +0 -0
  732. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_release_cordon_daemon_leads_2176.py +0 -0
  733. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_release_cordon_deadlock_2240.py +0 -0
  734. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_release_cordon_stuck_2490.py +0 -0
  735. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_release_propagate.py +0 -0
  736. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_release_propagate_threshold.py +0 -0
  737. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_release_roll_between_legs_2854.py +0 -0
  738. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_release_roll_window_handoff.py +0 -0
  739. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_release_unified_1242.py +0 -0
  740. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_release_verify.py +0 -0
  741. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_release_window.py +0 -0
  742. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_remote_auto_prune.py +0 -0
  743. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_remote_interactive_reaper.py +0 -0
  744. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_repo_add.py +0 -0
  745. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_repo_dormancy.py +0 -0
  746. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_repo_edit_2220.py +0 -0
  747. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_repo_graph_fleet_2237.py +0 -0
  748. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_repo_onboard_2220.py +0 -0
  749. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_report_result_push.py +0 -0
  750. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_reports.py +0 -0
  751. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_retry.py +0 -0
  752. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_retry_advisory_1606.py +0 -0
  753. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_retry_type_1636.py +0 -0
  754. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_revalidate.py +0 -0
  755. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_review.py +0 -0
  756. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_review_end_review_without_verdict.py +0 -0
  757. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_review_parse_failure_diagnostic.py +0 -0
  758. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_review_reaffirm.py +0 -0
  759. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_review_state.py +0 -0
  760. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_review_verdict_backstop.py +0 -0
  761. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_review_verdict_override_audit.py +0 -0
  762. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_review_verdict_relay.py +0 -0
  763. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_review_zero_commits.py +0 -0
  764. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_scoped_review_wiring.py +0 -0
  765. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_scorecard.py +0 -0
  766. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_self_health.py +0 -0
  767. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_serve.py +0 -0
  768. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_serve_app_board_trim.py +0 -0
  769. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_serve_rest_routes.py +0 -0
  770. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_session.py +0 -0
  771. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_slice_issue_attribution.py +0 -0
  772. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_smoke.py +0 -0
  773. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_smoke_live_checkout_restore.py +0 -0
  774. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_smoke_workflow.py +0 -0
  775. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_spend_ceiling.py +0 -0
  776. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_spend_ceiling_coordinator.py +0 -0
  777. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_split.py +0 -0
  778. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_split_work.py +0 -0
  779. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_sql_dialect.py +0 -0
  780. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_stage_projection.py +0 -0
  781. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_stale_busy_reviewer_697.py +0 -0
  782. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_stalled_pipeline.py +0 -0
  783. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_state.py +0 -0
  784. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_state_review_findings_daemon.py +0 -0
  785. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_status_fleet_footer.py +0 -0
  786. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_stop_1567.py +0 -0
  787. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_store_contract.py +0 -0
  788. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_store_migrate.py +0 -0
  789. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_stuck.py +0 -0
  790. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_stuck_test_state_watchdog_2803.py +0 -0
  791. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_terminal_command.py +0 -0
  792. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_test_author.py +0 -0
  793. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_test_chat.py +0 -0
  794. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_test_orchestrator.py +0 -0
  795. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_test_report.py +0 -0
  796. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_test_verdict_parsing.py +0 -0
  797. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_test_verdict_transcript_floor.py +0 -0
  798. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_text_io_encoding_audit.py +0 -0
  799. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_thin_client_board_audit.py +0 -0
  800. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_thin_client_config_load_1080.py +0 -0
  801. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_thin_client_daemon_routing_906.py +0 -0
  802. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_tmux_host.py +0 -0
  803. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_tmux_session.py +0 -0
  804. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_transcript_floor.py +0 -0
  805. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_usage.py +0 -0
  806. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_usage_limits.py +0 -0
  807. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_usage_rollup.py +0 -0
  808. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_venv_live_install_2121.py +0 -0
  809. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_version_single_source.py +0 -0
  810. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_watch.py +0 -0
  811. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_windows_job_is_a_real_gate_2000.py +0 -0
  812. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_worker_env_venv_isolation.py +0 -0
  813. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_worker_events.py +0 -0
  814. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_worker_image_pin_sync.py +0 -0
  815. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_worker_safety.py +0 -0
  816. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_worker_test_scoping.py +0 -0
  817. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_worktree.py +0 -0
  818. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_worktree_rmtree_chokepoint.py +0 -0
  819. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/test_write_parity.py +0 -0
  820. {code_coordinator-0.5.318 → code_coordinator-0.5.320}/tests/write_parity.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-coordinator
3
- Version: 0.5.318
3
+ Version: 0.5.320
4
4
  Summary: Coordinate Claude Code workers across multiple machines and repos.
5
5
  Author-email: John Donaghy <johnfdonaghy@gmail.com>
6
6
  License-Expression: LicenseRef-FSL-1.1-MIT
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-coordinator
3
- Version: 0.5.318
3
+ Version: 0.5.320
4
4
  Summary: Coordinate Claude Code workers across multiple machines and repos.
5
5
  Author-email: John Donaghy <johnfdonaghy@gmail.com>
6
6
  License-Expression: LicenseRef-FSL-1.1-MIT
@@ -1,7 +1,7 @@
1
1
  {
2
- "tag": "0.5.318",
2
+ "tag": "0.5.320",
3
3
  "distance": 0,
4
- "node": "g232148cbec6041ecf0afda964794347d61a21a64",
4
+ "node": "g83f3ac495a1b16e3129d8654f1f061934acdc32c",
5
5
  "dirty": false,
6
6
  "branch": "HEAD",
7
7
  "node_date": "2026-08-31"
@@ -55,6 +55,15 @@ machine can be briefed without a prior session's transcript, so ``ledger``
55
55
  ``POST /portal-decision`` — both through :mod:`coord.portal_store`, which
56
56
  checks ``board_service`` itself rather than calling
57
57
  :func:`_refuse_if_thin_client`. See that section below for the detail.
58
+
59
+ **``note`` (#2867) and ``answer`` (#2986) are the ledger's two operator-only
60
+ writes.** ``note`` records background with no pairing and no status effect;
61
+ ``answer`` records a client's answer that arrived OUT OF BAND — verbally, on
62
+ a call, by email — pairs it to the open question's ``question_revision``
63
+ exactly like an inbound ``question.answered`` event does, flags it relayed
64
+ so it never reads as the client's own words, and folds the submission off
65
+ ``needs-input``. Same daemon-routed shape (``POST /portal-note`` /
66
+ ``POST /portal-answer``) and the same reason.
58
67
  """
59
68
 
60
69
  from __future__ import annotations
@@ -1792,6 +1801,25 @@ def portal_draft_reject(
1792
1801
  # it's set).
1793
1802
 
1794
1803
 
1804
+ def _render_answer_line(a: dict, *, indent: str) -> str:
1805
+ """One rendered answer line — plain when it's the client's own words,
1806
+ visibly RELAYED (source + date + operator actor) when it isn't (#2986's
1807
+ acceptance bar: a relayed answer must never be presentable as something
1808
+ the client typed themselves). ``.get`` throughout because a thin client
1809
+ talking to a daemon that predates #2986 returns a payload with neither
1810
+ key."""
1811
+ if not a.get("relayed"):
1812
+ return f"{indent}A: {a['text']} (by {a['actor'] or 'customer'})"
1813
+ when = datetime.datetime.fromtimestamp(
1814
+ a["recorded_at"], tz=datetime.timezone.utc
1815
+ ).strftime("%Y-%m-%d %H:%M UTC")
1816
+ source = a.get("source") or "unknown"
1817
+ return (
1818
+ f"{indent}A [RELAYED via {source}, {when}, by {a['actor'] or 'operator'}]: "
1819
+ f"{a['text']}"
1820
+ )
1821
+
1822
+
1795
1823
  def _render_ledger_text(payload: dict) -> str:
1796
1824
  """The human-readable rendering of :func:`coord.portal_store.
1797
1825
  render_ledger_payload`'s dict shape — used identically whether *payload*
@@ -1807,12 +1835,13 @@ def _render_ledger_text(payload: dict) -> str:
1807
1835
  lines.append(f"- Q[{label}] {entry['question']}")
1808
1836
  if entry["answers"]:
1809
1837
  for a in entry["answers"]:
1810
- lines.append(f" A: {a['text']} (by {a['actor'] or 'customer'})")
1838
+ lines.append(_render_answer_line(a, indent=" "))
1811
1839
  else:
1812
1840
  lines.append(" (unanswered — needs-input)")
1813
1841
  for a in unpaired:
1842
+ tag = " RELAYED" if a.get("relayed") else ""
1814
1843
  lines.append(
1815
- f"- A (unpaired, question_revision={a['question_revision']}): "
1844
+ f"- A{tag} (unpaired, question_revision={a['question_revision']}): "
1816
1845
  f"{a['text']} (by {a['actor'] or 'customer'})"
1817
1846
  )
1818
1847
 
@@ -1995,3 +2024,90 @@ def portal_decision_supersede(submission_id: str, seq: int, by_seq: int) -> None
1995
2024
  click.secho(
1996
2025
  f"superseded: {submission_id} #{entry.seq} -> #{by_seq}", fg="green"
1997
2026
  )
2027
+
2028
+
2029
+ # ── #2986: `coord portal answer` — record an out-of-band answer ────────────
2030
+
2031
+
2032
+ @portal_group.command("answer")
2033
+ @_CONFIG_OPTION
2034
+ @click.argument("submission_id")
2035
+ @click.argument("text")
2036
+ @click.option(
2037
+ "--source",
2038
+ type=click.Choice(("verbal", "phone", "email")),
2039
+ default="verbal",
2040
+ show_default=True,
2041
+ help="How the answer actually reached you.",
2042
+ )
2043
+ @click.option(
2044
+ "--revision",
2045
+ "revision",
2046
+ type=int,
2047
+ default=None,
2048
+ help=(
2049
+ "Target an older question's revision instead of the current open "
2050
+ "one — backfills a question answered before this command existed."
2051
+ ),
2052
+ )
2053
+ def portal_answer(
2054
+ config_path, submission_id: str, text: str, source: str, revision: int | None
2055
+ ) -> None:
2056
+ """Record an answer SUBMISSION_ID's client gave OUT OF BAND — in
2057
+ person, on a call, by email (#2986).
2058
+
2059
+ The ledger's own writer, ``coord/portal_sync.py:_record_question_
2060
+ answer``, only ever fires off an inbound ``question.answered`` event —
2061
+ so an answer that arrives any other way had nowhere to land as an
2062
+ ANSWER, and the ledger kept rendering the question ``(unanswered —
2063
+ needs-input)`` long after it was actually answered. This pairs TEXT to
2064
+ the same open question (by ``question_revision``) that consumer pairs
2065
+ to, flags it as relayed (never presentable as the client's own words —
2066
+ see ``coord portal ledger``'s rendering), and nudges the submission off
2067
+ ``needs-input`` the same way the inbound consumer does.
2068
+
2069
+ With no ``--revision``, targets whatever question is currently open. A
2070
+ submission with no open question (everything already answered, or no
2071
+ question ever pushed) is a clear error — pass ``--revision`` to backfill
2072
+ an older, already-superseded question instead (SUB-1EA1D3's Q[11], asked
2073
+ alongside Q[13] and answered before Q[13] was).
2074
+
2075
+ Like ``note``/``decision``/``link`` (#2751) this is not thin-client-
2076
+ refused — it routes through the daemon's ``/portal-answer`` seam when
2077
+ ``board_service`` is configured, so it works from wherever the operator
2078
+ happens to be.
2079
+ """
2080
+ from coord import portal_store # noqa: PLC0415
2081
+ from coord.board_service import resolve # noqa: PLC0415
2082
+
2083
+ # Config is only needed for the "leave needs-input" fold nudge, and only
2084
+ # when THIS process is the one that will actually run it — i.e. it is
2085
+ # not a thin client (a thin client's write routes through
2086
+ # `/portal-answer`, and the daemon folds status there with its OWN
2087
+ # config; see `coord.serve_app`'s handler). Loading it unconditionally
2088
+ # would cost a thin client an extra `fetch_remote_config` round trip for
2089
+ # a value it would never use. Best-effort either way — a config that
2090
+ # fails to resolve degrades to no fold nudge, same as passing `None`.
2091
+ config = None
2092
+ if resolve() is None:
2093
+ try:
2094
+ config = _load_config(config_path)
2095
+ except Exception: # noqa: BLE001 — the nudge is best-effort, not this command
2096
+ config = None
2097
+ try:
2098
+ entry = portal_store.answer_question(
2099
+ submission_id,
2100
+ text,
2101
+ source=source,
2102
+ revision=revision,
2103
+ actor=_actor(),
2104
+ config=config,
2105
+ )
2106
+ except ValueError as exc:
2107
+ click.secho(f"error: {exc}", fg="red")
2108
+ raise SystemExit(2) from exc
2109
+ click.secho(
2110
+ f"answered: {submission_id} Q[{entry.question_revision}] via {source} "
2111
+ f"(by {entry.actor}) — {entry.text}",
2112
+ fg="green",
2113
+ )
@@ -1775,13 +1775,27 @@ def _migrate_add_columns(conn: sqlite3.Connection) -> None:
1775
1775
  error raised for a duplicate column (SQLite's ``OperationalError``;
1776
1776
  Postgres's equivalent under ``sql.driver_errors()``, #2784) is silently
1777
1777
  swallowed.
1778
+
1779
+ #2982: Postgres aborts the whole transaction on a failed statement, so
1780
+ without a ``conn.rollback()`` here the *first* duplicate ALTER (every
1781
+ entry in ``_MIGRATE_ADD_COLUMNS`` is one, against a freshly-created
1782
+ schema) leaves the connection unusable -- every statement after it,
1783
+ including the remaining ALTERs and ``_set_schema_version``'s own
1784
+ ``DELETE FROM schema_version``, fails with
1785
+ ``psycopg.errors.InFailedSqlTransaction``. SQLite has no such concept
1786
+ (a failed statement there doesn't touch the transaction), so the
1787
+ rollback is a no-op on that backend -- and by this point in
1788
+ ``_ensure_schema`` there is nothing uncommitted to lose on either
1789
+ backend: the schema script already committed, and each successful ALTER
1790
+ in this loop commits immediately, so a rollback can only ever discard
1791
+ the one statement that just failed.
1778
1792
  """
1779
1793
  for ddl in _MIGRATE_ADD_COLUMNS:
1780
1794
  try:
1781
1795
  sql.execute(conn, ddl)
1782
1796
  conn.commit()
1783
1797
  except sql.driver_errors():
1784
- pass # Column already exists
1798
+ conn.rollback() # Column already exists; Postgres needs the tx cleared
1785
1799
 
1786
1800
 
1787
1801
  # ── JSON migration ─────────────────────────────────────────────────────────────
@@ -37,6 +37,7 @@ posture every other dispatcher in this file already uses.
37
37
  """
38
38
  from __future__ import annotations
39
39
 
40
+ import datetime
40
41
  import time
41
42
  import uuid
42
43
  from typing import TYPE_CHECKING, Any
@@ -271,6 +272,34 @@ def fetch_running_context(submission_id: str) -> dict[str, Any]:
271
272
  return portal_store.render_ledger_payload(submission_id)
272
273
 
273
274
 
275
+ def _render_answer_line(a: dict[str, Any]) -> str:
276
+ """One rendered answer line — mirrors :func:`coord.commands.portal.
277
+ _render_answer_line` exactly (kept as a separate copy since the two
278
+ modules render different surrounding structure — a plain-text agent
279
+ briefing here, ``coord portal ledger``'s CLI output there).
280
+
281
+ #2986: a relayed (out-of-band) answer must never read as something the
282
+ client typed themselves — a session briefed from this text has no other
283
+ way to tell the difference, so the RELAYED tag, its source, and when it
284
+ was recorded are load-bearing here, not cosmetic. ``.get`` throughout
285
+ because a thin client's daemon may predate #2986 and never sets either
286
+ key."""
287
+ if not a.get("relayed"):
288
+ return f"A: {a.get('text', '')} (by {a.get('actor') or 'customer'})"
289
+ recorded_at = a.get("recorded_at")
290
+ when = (
291
+ datetime.datetime.fromtimestamp(recorded_at, tz=datetime.timezone.utc)
292
+ .strftime("%Y-%m-%d %H:%M UTC")
293
+ if recorded_at
294
+ else "unknown date"
295
+ )
296
+ source = a.get("source") or "unknown"
297
+ return (
298
+ f"A [RELAYED via {source}, {when}, by {a.get('actor') or 'operator'}]: "
299
+ f"{a.get('text', '')}"
300
+ )
301
+
302
+
274
303
  def render_running_context_section(payload: dict[str, Any]) -> str:
275
304
  """Render *payload* (:func:`fetch_running_context`'s shape) as the
276
305
  briefing's RUNNING CONTEXT section — every question asked and its
@@ -295,14 +324,13 @@ def render_running_context_section(payload: dict[str, Any]) -> str:
295
324
  answers = entry.get("answers") or []
296
325
  if answers:
297
326
  for a in answers:
298
- lines.append(
299
- f" A: {a.get('text', '')} (by {a.get('actor') or 'customer'})"
300
- )
327
+ lines.append(f" {_render_answer_line(a)}")
301
328
  else:
302
329
  lines.append(" (unanswered — needs-input)")
303
330
  for a in unpaired:
331
+ tag = " RELAYED" if a.get("relayed") else ""
304
332
  lines.append(
305
- f" - A (unpaired, question_revision={a.get('question_revision')}): "
333
+ f" - A{tag} (unpaired, question_revision={a.get('question_revision')}): "
306
334
  f"{a.get('text', '')} (by {a.get('actor') or 'customer'})"
307
335
  )
308
336
 
@@ -39,6 +39,7 @@ from __future__ import annotations
39
39
 
40
40
  import hashlib
41
41
  import json
42
+ import logging
42
43
  import sqlite3
43
44
  import time
44
45
  from dataclasses import dataclass
@@ -46,6 +47,8 @@ from typing import Any, Mapping
46
47
 
47
48
  from coord import sql
48
49
 
50
+ _log = logging.getLogger(__name__)
51
+
49
52
  #: A DB-API row as the three ``_*_from_row`` helpers below need it: index by
50
53
  #: column name (``row["col"]``). ``sqlite3.Row`` and psycopg's ``dict_row``
51
54
  #: rows (plain ``dict``s) both satisfy this, so the helpers name neither
@@ -1756,6 +1759,16 @@ LEDGER_KIND_OPERATOR_NOTE = "operator_note"
1756
1759
  #: the client actually wrote. See :func:`operator_actor`.
1757
1760
  OPERATOR_ACTOR_PREFIX = "operator:"
1758
1761
 
1762
+ #: #2986: how an out-of-band answer actually reached the operator —
1763
+ #: ``coord portal answer --source``. Recorded in the ledger row's
1764
+ #: ``payload`` (``{"relayed": True, "source": ...}``) so a renderer can
1765
+ #: attribute it as relayed rather than presenting it as the client's own
1766
+ #: words (this issue's acceptance bar). "verbal" (in person or a call the
1767
+ #: operator wasn't dialing in from, i.e. no better label applies) is the
1768
+ #: default — the common case for a small engagement.
1769
+ RELAYED_ANSWER_SOURCES = ("verbal", "phone", "email")
1770
+ DEFAULT_RELAYED_ANSWER_SOURCE = "verbal"
1771
+
1759
1772
 
1760
1773
  def operator_actor(name: str = "") -> str:
1761
1774
  """The ``actor`` string for an operator-authored ledger row.
@@ -1981,6 +1994,198 @@ def append_operator_note(
1981
1994
  return _append_operator_note_local(submission_id, text, actor=actor, now=now)
1982
1995
 
1983
1996
 
1997
+ # ── layer 1b: relayed answers (#2986) ────────────────────────────────────────
1998
+ #
1999
+ # The one write path this issue adds: an answer the operator received OUT OF
2000
+ # BAND — in person, on a call, by email — and needs paired to the question's
2001
+ # own ``question_revision`` exactly the way an inbound ``question.answered``
2002
+ # event already is (:func:`coord.portal_sync._record_question_answer`). Still
2003
+ # ledger-class (see this section's ownership note above): a human relaying
2004
+ # what the customer told them is coord-observed the same way an operator note
2005
+ # (#2867) is, not an agent's say-so. Unlike a note, this DOES pair to a
2006
+ # question and DOES nudge the submission off ``needs-input`` — the two things
2007
+ # `note` deliberately does not do (see `append_operator_note`'s docstring).
2008
+
2009
+
2010
+ def _current_open_question_revision(submission_id: str) -> int | None:
2011
+ """The most recently pushed question for *submission_id* that has no
2012
+ ledgered answer yet, or ``None`` if every pushed question already has
2013
+ one (or none has ever been pushed).
2014
+
2015
+ Mirrors the pairing :func:`render_ledger_payload` does for display —
2016
+ keyed on ``question_revision``, oldest push first — but only needs the
2017
+ "still open" half, not the full answers list.
2018
+ """
2019
+ pushed_revisions: list[int | None] = []
2020
+ answered_revisions: set[int | None] = set()
2021
+ for entry in ledger_for_submission(submission_id):
2022
+ if entry.kind == LEDGER_KIND_QUESTION_PUSHED:
2023
+ pushed_revisions.append(entry.question_revision)
2024
+ elif entry.kind == LEDGER_KIND_QUESTION_ANSWERED:
2025
+ answered_revisions.add(entry.question_revision)
2026
+ open_revisions = [r for r in pushed_revisions if r not in answered_revisions]
2027
+ if not open_revisions:
2028
+ return None
2029
+ return open_revisions[-1]
2030
+
2031
+
2032
+ def _fold_status_after_answer(config: Any, submission_id: str) -> None:
2033
+ """Best-effort nudge off ``needs-input`` after a relayed answer lands
2034
+ (#2986) — the same courtesy :func:`coord.portal_sync._record_question_
2035
+ answer` performs for an inbound ``question.answered`` event, so an
2036
+ out-of-band answer leaves ``needs-input`` on the same tick as the write
2037
+ rather than waiting on the next unconditional status fold.
2038
+
2039
+ Never raises: a courtesy nudge, not the recorded fact itself. ``config``
2040
+ is optional the same way :func:`coord.portal_sync._record_question_
2041
+ answer`'s is — the CLI-local path always has one, but a test exercising
2042
+ just the ledger write can omit it and get a no-op here instead of an
2043
+ import-time failure.
2044
+ """
2045
+ if config is None:
2046
+ return
2047
+ try:
2048
+ from coord import portal_sync # noqa: PLC0415
2049
+
2050
+ link = get_link_by_submission(submission_id)
2051
+ if link is None:
2052
+ return
2053
+ repo_cfg = config.repo(link.repo_name)
2054
+ if repo_cfg is None:
2055
+ return
2056
+ if link.issue_number is not None:
2057
+ portal_sync.fold_status_for_issue(config, link.repo_name, link.issue_number)
2058
+ else:
2059
+ portal_sync.fold_status_for_milestone(
2060
+ config, link.repo_name, link.milestone_number
2061
+ )
2062
+ except Exception: # noqa: BLE001 — a courtesy nudge, not the recorded fact itself
2063
+ _log.warning(
2064
+ "portal answer: could not fold status after relayed answer for %s",
2065
+ submission_id,
2066
+ exc_info=True,
2067
+ )
2068
+
2069
+
2070
+ def _answer_question_local(
2071
+ submission_id: str,
2072
+ text: str,
2073
+ *,
2074
+ source: str = DEFAULT_RELAYED_ANSWER_SOURCE,
2075
+ revision: int | None = None,
2076
+ actor: str = "",
2077
+ config: Any = None,
2078
+ now: float | None = None,
2079
+ ) -> LedgerEntry:
2080
+ """Write half of :func:`answer_question` — runs on the daemon host
2081
+ (either directly, or via ``/portal-answer`` on behalf of a thin client).
2082
+
2083
+ Same "validate the submission HERE" reasoning as
2084
+ :func:`_append_operator_note_local`. ``revision=None`` targets whatever
2085
+ :func:`_current_open_question_revision` currently considers open;
2086
+ passing an explicit ``revision`` backfills an older, already-superseded
2087
+ question (SUB-1EA1D3's Q[11] fixture case, #2986) and skips that lookup
2088
+ entirely — even a revision with no matching pushed question is still
2089
+ ledgered (it lands in ``unpaired_answers``, same tolerance
2090
+ :func:`coord.portal_sync._record_question_answer` already has for a
2091
+ malformed inbound event).
2092
+ """
2093
+ if not submission_id or not submission_id.strip():
2094
+ raise ValueError("answer needs a submission_id")
2095
+ if not text or not text.strip():
2096
+ raise ValueError("answer needs non-empty text")
2097
+ if get_submission(submission_id) is None:
2098
+ raise ValueError(
2099
+ f"unknown submission {submission_id!r} — no portal submission with "
2100
+ "that id (check `coord portal status` for the current ids)"
2101
+ )
2102
+ src = (source or DEFAULT_RELAYED_ANSWER_SOURCE).strip().lower()
2103
+ if src not in RELAYED_ANSWER_SOURCES:
2104
+ raise ValueError(
2105
+ f"unknown --source {source!r} — choose one of "
2106
+ f"{', '.join(RELAYED_ANSWER_SOURCES)}"
2107
+ )
2108
+ target_revision = revision
2109
+ if target_revision is None:
2110
+ target_revision = _current_open_question_revision(submission_id)
2111
+ if target_revision is None:
2112
+ raise ValueError(
2113
+ f"no open question on file for {submission_id!r} — nothing to "
2114
+ "answer (pass --revision to backfill an older question)"
2115
+ )
2116
+ entry = append_ledger_entry(
2117
+ submission_id,
2118
+ LEDGER_KIND_QUESTION_ANSWERED,
2119
+ question_revision=target_revision,
2120
+ text=text.strip(),
2121
+ actor=operator_actor(actor),
2122
+ payload={"relayed": True, "source": src},
2123
+ now=now,
2124
+ )
2125
+ _fold_status_after_answer(config, submission_id)
2126
+ return entry
2127
+
2128
+
2129
+ def _route_answer(payload: dict[str, Any]) -> dict[str, Any] | None:
2130
+ """POST *payload* to the daemon's ``/portal-answer`` seam, or ``None`` if
2131
+ this process IS the daemon host — the relayed-answer twin of
2132
+ :func:`_route_note`, daemon-routed for the same #2751 reason: the
2133
+ operator relaying an out-of-band answer may be sitting at any machine in
2134
+ the fleet, and a write into a thin client's own empty ``portal_ledger``
2135
+ would be silently lost.
2136
+ """
2137
+ from coord import board_service # noqa: PLC0415
2138
+
2139
+ svc = board_service.resolve()
2140
+ return board_service.route_write(svc, "/portal-answer", payload)
2141
+
2142
+
2143
+ def answer_question(
2144
+ submission_id: str,
2145
+ text: str,
2146
+ *,
2147
+ source: str = DEFAULT_RELAYED_ANSWER_SOURCE,
2148
+ revision: int | None = None,
2149
+ actor: str = "",
2150
+ config: Any = None,
2151
+ now: float | None = None,
2152
+ ) -> LedgerEntry:
2153
+ """Record an answer the operator received OUT OF BAND (#2986) —
2154
+ ``coord portal answer`` — routed to the daemon when ``board_service`` is
2155
+ configured, else written (and folded) locally.
2156
+
2157
+ Raises :class:`ValueError` for an unknown submission, empty text, an
2158
+ unknown ``source``, or (with no ``revision`` given) no open question on
2159
+ file. The stored text is VERBATIM and flagged ``relayed`` in the ledger
2160
+ row's payload, never presentable as the client's own words (see
2161
+ :func:`render_ledger_payload`'s ``qa[*]["answers"][*]["relayed"]``). A
2162
+ later inbound ``question.answered`` for the same revision
2163
+ (:func:`coord.portal_sync._record_question_answer`) is additive, not a
2164
+ conflict: the ledger is append-only, so both rows coexist under the same
2165
+ ``question_revision`` in the order they were recorded.
2166
+ """
2167
+ routed = _route_answer(
2168
+ {
2169
+ "submission_id": submission_id,
2170
+ "text": text,
2171
+ "source": source,
2172
+ "revision": revision,
2173
+ "actor": actor,
2174
+ }
2175
+ )
2176
+ if routed is not None:
2177
+ return _ledger_from_row(routed["entry"])
2178
+ return _answer_question_local(
2179
+ submission_id,
2180
+ text,
2181
+ source=source,
2182
+ revision=revision,
2183
+ actor=actor,
2184
+ config=config,
2185
+ now=now,
2186
+ )
2187
+
2188
+
1984
2189
  # ── layer 2: decisions (agent-authored, operator-confirmed) ─────────────────
1985
2190
 
1986
2191
  DECISION_PROPOSED = "proposed"
@@ -2356,7 +2561,18 @@ def render_ledger_payload(submission_id: str) -> dict[str, Any]:
2356
2561
  "question_revision": revision,
2357
2562
  "question": qa["question"].text,
2358
2563
  "answers": [
2359
- {"text": a.text, "actor": a.actor, "recorded_at": a.recorded_at}
2564
+ {
2565
+ "text": a.text,
2566
+ "actor": a.actor,
2567
+ "recorded_at": a.recorded_at,
2568
+ # #2986: attribution for an out-of-band answer — set
2569
+ # only by `answer_question`/`coord portal answer`, so
2570
+ # a renderer can tell "the client's own words" from
2571
+ # "the operator relayed this" rather than the two
2572
+ # looking identical.
2573
+ "relayed": bool(a.payload.get("relayed")),
2574
+ "source": a.payload.get("source", ""),
2575
+ }
2360
2576
  for a in qa["answers"]
2361
2577
  ],
2362
2578
  }
@@ -2368,6 +2584,8 @@ def render_ledger_payload(submission_id: str) -> dict[str, Any]:
2368
2584
  "text": a.text,
2369
2585
  "actor": a.actor,
2370
2586
  "recorded_at": a.recorded_at,
2587
+ "relayed": bool(a.payload.get("relayed")),
2588
+ "source": a.payload.get("source", ""),
2371
2589
  }
2372
2590
  for a in unpaired_answers
2373
2591
  ],
@@ -3419,6 +3419,53 @@ def openapi_spec() -> dict:
3419
3419
  },
3420
3420
  },
3421
3421
  },
3422
+ "/portal-answer": {
3423
+ "post": {
3424
+ "summary": (
3425
+ "#2986: record an answer received OUT OF BAND (verbal/"
3426
+ "phone/email) against a submission's open question, "
3427
+ "paired to its question_revision and flagged relayed. "
3428
+ "Executed HERE on the daemon, same reason /portal-note "
3429
+ "is — `coord portal answer`"
3430
+ ),
3431
+ "requestBody": {
3432
+ "required": True,
3433
+ "content": {
3434
+ "application/json": {
3435
+ "schema": {
3436
+ "type": "object",
3437
+ "properties": {
3438
+ "submission_id": {"type": "string"},
3439
+ "text": {"type": "string"},
3440
+ "source": {
3441
+ "type": "string",
3442
+ "enum": ["verbal", "phone", "email"],
3443
+ },
3444
+ "revision": {
3445
+ "type": "integer",
3446
+ "description": (
3447
+ "Backfill an older question instead "
3448
+ "of the current open one."
3449
+ ),
3450
+ },
3451
+ "actor": {"type": "string"},
3452
+ },
3453
+ "required": ["submission_id", "text"],
3454
+ }
3455
+ }
3456
+ },
3457
+ },
3458
+ "responses": {
3459
+ "200": {"description": "OK — {'entry': <serialized LedgerEntry>}"},
3460
+ "400": {
3461
+ "description": (
3462
+ "Missing submission_id, empty text, unknown source, "
3463
+ "unknown submission, or no open question on file"
3464
+ )
3465
+ },
3466
+ },
3467
+ },
3468
+ },
3422
3469
  "/portal-ledger": {
3423
3470
  "get": {
3424
3471
  "summary": (
@@ -6459,6 +6506,69 @@ def build_app(store: CoordStore, config: Config, *, token: str | None = None) ->
6459
6506
  }
6460
6507
  )
6461
6508
 
6509
+ async def post_portal_answer(request: Request) -> Response:
6510
+ # #2986: record an out-of-band answer (verbal/phone/email) against a
6511
+ # submission's open question. Same seam shape and same rationale as
6512
+ # `/portal-note`/`/portal-decision` right above — the operator may be
6513
+ # relaying this from any machine in the fleet — but unlike a note,
6514
+ # this pairs to a question's own `question_revision` and folds the
6515
+ # customer status off `needs-input` HERE, on the daemon, using this
6516
+ # process's own `config` (the closure variable `build_app` sets up
6517
+ # and `_refresh_config` keeps current) rather than anything the
6518
+ # caller could hand over the wire.
6519
+ import json as _json # noqa: PLC0415
6520
+
6521
+ from coord import portal_store # noqa: PLC0415
6522
+
6523
+ body = await _read_json(request)
6524
+ if body is None:
6525
+ return JSONResponse({"error": "invalid JSON body"}, status_code=400)
6526
+ submission_id = body.get("submission_id")
6527
+ if not isinstance(submission_id, str) or not submission_id:
6528
+ return JSONResponse(
6529
+ {"error": "portal-answer needs a 'submission_id'"}, status_code=400
6530
+ )
6531
+ revision = body.get("revision")
6532
+ if revision is not None and not isinstance(revision, int):
6533
+ return JSONResponse(
6534
+ {"error": "portal-answer 'revision' must be an integer"},
6535
+ status_code=400,
6536
+ )
6537
+ try:
6538
+ entry = portal_store._answer_question_local(
6539
+ submission_id,
6540
+ body.get("text") or "",
6541
+ source=body.get("source") or portal_store.DEFAULT_RELAYED_ANSWER_SOURCE,
6542
+ revision=revision,
6543
+ actor=body.get("actor") or "",
6544
+ config=config,
6545
+ )
6546
+ except ValueError as e:
6547
+ return JSONResponse({"error": f"bad portal-answer: {e}"}, status_code=400)
6548
+ except Exception as e: # noqa: BLE001
6549
+ return JSONResponse(
6550
+ {"error": "portal-answer write failed", "detail": str(e)},
6551
+ status_code=503,
6552
+ )
6553
+ return JSONResponse(
6554
+ {
6555
+ "entry": {
6556
+ "id": entry.id,
6557
+ "submission_id": entry.submission_id,
6558
+ "seq": entry.seq,
6559
+ "kind": entry.kind,
6560
+ "question_revision": entry.question_revision,
6561
+ "text": entry.text,
6562
+ "actor": entry.actor,
6563
+ "source_event_id": entry.source_event_id,
6564
+ # Same reconstruction contract as `/portal-note` above —
6565
+ # `_ledger_from_row` parses this as a JSON *string*.
6566
+ "payload_json": _json.dumps(entry.payload, sort_keys=True),
6567
+ "recorded_at": entry.recorded_at,
6568
+ }
6569
+ }
6570
+ )
6571
+
6462
6572
  async def get_portal_ledger(request: Request) -> Response:
6463
6573
  # #2749 (IL-3): render one submission's running-context briefing on
6464
6574
  # the daemon and hand back the same JSON shape
@@ -9795,6 +9905,7 @@ def build_app(store: CoordStore, config: Config, *, token: str | None = None) ->
9795
9905
  Route("/portal-link", post_portal_link, methods=["POST"]),
9796
9906
  Route("/portal-decision", post_portal_decision, methods=["POST"]),
9797
9907
  Route("/portal-note", post_portal_note, methods=["POST"]),
9908
+ Route("/portal-answer", post_portal_answer, methods=["POST"]),
9798
9909
  Route("/portal-ledger", get_portal_ledger, methods=["GET"]),
9799
9910
  Route("/dispatched", post_dispatched, methods=["POST"]),
9800
9911
  Route("/test-verdict", post_test_verdict, methods=["POST"]),