project-agent 0.2.4__tar.gz → 0.2.5__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 (282) hide show
  1. {project_agent-0.2.4 → project_agent-0.2.5}/PKG-INFO +1 -1
  2. {project_agent-0.2.4 → project_agent-0.2.5}/pyproject.toml +3 -1
  3. project_agent-0.2.5/src/project_agent/application/bootstrap/apply.py +222 -0
  4. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/bootstrap/checkpoint.py +20 -29
  5. project_agent-0.2.5/src/project_agent/application/bootstrap/contracts.py +80 -0
  6. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/bootstrap/init.py +12 -12
  7. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/bootstrap/loop_state.py +1 -1
  8. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/context/get_project_context.py +66 -10
  9. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/context/get_user_context.py +1 -0
  10. project_agent-0.2.5/src/project_agent/application/context/list_core_relationships.py +34 -0
  11. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/context/project_summary.py +91 -0
  12. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/context/resolve_user.py +25 -2
  13. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/context/search_user.py +1 -0
  14. project_agent-0.2.5/src/project_agent/application/context/set_project_owner.py +227 -0
  15. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/context/upsert_user_identity.py +4 -0
  16. project_agent-0.2.5/src/project_agent/application/context/workstreams.py +248 -0
  17. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/doc/render.py +407 -242
  18. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/doc/sync.py +36 -9
  19. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/doc/writeback.py +9 -9
  20. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/doc_hub/manage.py +159 -20
  21. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/doc_hub/read.py +60 -18
  22. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/loop/enqueue.py +8 -4
  23. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/loop/run.py +56 -24
  24. project_agent-0.2.4/src/project_agent/application/mind/create_version.py → project_agent-0.2.5/src/project_agent/application/mind/create_sprint.py +77 -58
  25. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/mind/delete_task.py +61 -29
  26. project_agent-0.2.4/src/project_agent/application/mind/finalize_version_closure.py → project_agent-0.2.5/src/project_agent/application/mind/finalize_sprint_closure.py +119 -97
  27. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/mind/milestones.py +3 -3
  28. project_agent-0.2.5/src/project_agent/application/mind/planned_sprints.py +29 -0
  29. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/mind/propose_change.py +262 -97
  30. project_agent-0.2.5/src/project_agent/application/mind/read.py +531 -0
  31. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/mind/set_tracking.py +22 -4
  32. project_agent-0.2.5/src/project_agent/application/mind/signoff_proposal.py +558 -0
  33. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/mind/snooze_task_reminder.py +12 -12
  34. project_agent-0.2.4/src/project_agent/application/mind/switch_version.py → project_agent-0.2.5/src/project_agent/application/mind/switch_sprint.py +49 -30
  35. project_agent-0.2.5/src/project_agent/application/mind/update_project.py +159 -0
  36. project_agent-0.2.5/src/project_agent/application/mind/update_sprint.py +300 -0
  37. project_agent-0.2.5/src/project_agent/application/mind/write_task_update.py +767 -0
  38. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/monitoring/evaluate_followups.py +61 -10
  39. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/monitoring/run.py +9 -0
  40. project_agent-0.2.5/src/project_agent/application/onboarding/__init__.py +1 -0
  41. project_agent-0.2.5/src/project_agent/application/onboarding/apply.py +307 -0
  42. project_agent-0.2.5/src/project_agent/application/onboarding/contracts.py +41 -0
  43. project_agent-0.2.5/src/project_agent/application/proposals/__init__.py +1 -0
  44. project_agent-0.2.5/src/project_agent/application/proposals/apply.py +358 -0
  45. project_agent-0.2.5/src/project_agent/application/proposals/contracts.py +53 -0
  46. project_agent-0.2.5/src/project_agent/application/query/__init__.py +4 -0
  47. project_agent-0.2.5/src/project_agent/application/query/apply.py +803 -0
  48. project_agent-0.2.5/src/project_agent/application/query/contracts.py +73 -0
  49. project_agent-0.2.5/src/project_agent/application/report/apply.py +106 -0
  50. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/report/build.py +369 -172
  51. project_agent-0.2.5/src/project_agent/application/report/contracts.py +38 -0
  52. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/scheduled/run.py +187 -86
  53. project_agent-0.2.5/src/project_agent/application/shared/actor.py +86 -0
  54. project_agent-0.2.5/src/project_agent/application/shared/core_relationship_read.py +338 -0
  55. project_agent-0.2.5/src/project_agent/application/shared/project_membership.py +20 -0
  56. project_agent-0.2.5/src/project_agent/application/shared/project_owner_revision.py +53 -0
  57. project_agent-0.2.5/src/project_agent/application/shared/project_reference.py +125 -0
  58. project_agent-0.2.5/src/project_agent/application/shared/scene_command.py +49 -0
  59. project_agent-0.2.5/src/project_agent/application/shared/workstream_revision.py +54 -0
  60. project_agent-0.2.5/src/project_agent/application/shared/workstreams.py +23 -0
  61. project_agent-0.2.5/src/project_agent/application/sprint_closure/__init__.py +7 -0
  62. project_agent-0.2.5/src/project_agent/application/sprint_closure/apply.py +437 -0
  63. project_agent-0.2.5/src/project_agent/application/sprint_closure/contracts.py +39 -0
  64. project_agent-0.2.5/src/project_agent/application/sprint_closure/evaluate.py +112 -0
  65. project_agent-0.2.5/src/project_agent/application/sprints/__init__.py +4 -0
  66. project_agent-0.2.5/src/project_agent/application/sprints/apply.py +821 -0
  67. project_agent-0.2.5/src/project_agent/application/sprints/contracts.py +164 -0
  68. project_agent-0.2.5/src/project_agent/application/tasks/__init__.py +5 -0
  69. project_agent-0.2.5/src/project_agent/application/tasks/apply.py +1381 -0
  70. project_agent-0.2.5/src/project_agent/application/tasks/backend.py +109 -0
  71. project_agent-0.2.5/src/project_agent/application/tasks/composite_write.py +111 -0
  72. project_agent-0.2.5/src/project_agent/application/tasks/contracts.py +264 -0
  73. project_agent-0.2.5/src/project_agent/application/tasks/migrate.py +74 -0
  74. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/bootstrap/models.py +8 -7
  75. project_agent-0.2.5/src/project_agent/domain/core_relationships.py +155 -0
  76. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/doc/models.py +4 -4
  77. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/doc_hub/models.py +57 -4
  78. project_agent-0.2.5/src/project_agent/domain/mind/approval.py +342 -0
  79. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/mind/models.py +174 -44
  80. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/monitoring/evaluator.py +2 -2
  81. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/monitoring/models.py +43 -9
  82. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/project_context/models.py +69 -34
  83. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/report/models.py +74 -81
  84. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/scheduled/models.py +3 -3
  85. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/shared/documents.py +10 -0
  86. project_agent-0.2.5/src/project_agent/domain/shared/project_mind_derived.py +145 -0
  87. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/shared/project_mind_readiness.py +9 -9
  88. project_agent-0.2.5/src/project_agent/domain/shared/sprints.py +10 -0
  89. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/shared/statuses.py +31 -4
  90. project_agent-0.2.5/src/project_agent/domain/shared/workstreams.py +56 -0
  91. project_agent-0.2.5/src/project_agent/domain/sprint_closure/__init__.py +13 -0
  92. {project_agent-0.2.4/src/project_agent/domain/version_closure → project_agent-0.2.5/src/project_agent/domain/sprint_closure}/evaluator.py +93 -74
  93. {project_agent-0.2.4/src/project_agent/domain/version_closure → project_agent-0.2.5/src/project_agent/domain/sprint_closure}/models.py +42 -29
  94. project_agent-0.2.5/src/project_agent/domain/tasks/__init__.py +1 -0
  95. project_agent-0.2.5/src/project_agent/domain/tasks/rules.py +42 -0
  96. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/user/models.py +4 -17
  97. project_agent-0.2.5/src/project_agent/infrastructure/bootstrap/__init__.py +1 -0
  98. project_agent-0.2.5/src/project_agent/infrastructure/bootstrap/apply_runtime.py +102 -0
  99. project_agent-0.2.5/src/project_agent/infrastructure/db/channel_rename.py +120 -0
  100. project_agent-0.2.5/src/project_agent/infrastructure/db/core_relationships.py +1815 -0
  101. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/infrastructure/db/repositories.py +618 -91
  102. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/infrastructure/db/schema.py +656 -17
  103. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/infrastructure/db/tables.py +157 -18
  104. project_agent-0.2.5/src/project_agent/infrastructure/onboarding/__init__.py +1 -0
  105. project_agent-0.2.5/src/project_agent/infrastructure/onboarding/apply_runtime.py +127 -0
  106. project_agent-0.2.5/src/project_agent/infrastructure/proposals/__init__.py +1 -0
  107. project_agent-0.2.5/src/project_agent/infrastructure/proposals/apply_runtime.py +498 -0
  108. project_agent-0.2.5/src/project_agent/infrastructure/reports/__init__.py +1 -0
  109. project_agent-0.2.5/src/project_agent/infrastructure/reports/apply_runtime.py +84 -0
  110. project_agent-0.2.5/src/project_agent/infrastructure/sprints/__init__.py +0 -0
  111. project_agent-0.2.5/src/project_agent/infrastructure/sprints/apply_runtime.py +603 -0
  112. project_agent-0.2.5/src/project_agent/infrastructure/sprints/rollover_runtime.py +222 -0
  113. project_agent-0.2.5/src/project_agent/infrastructure/task_center/__init__.py +1 -0
  114. project_agent-0.2.5/src/project_agent/infrastructure/task_center/client.py +466 -0
  115. project_agent-0.2.5/src/project_agent/infrastructure/task_center/mapping.py +329 -0
  116. project_agent-0.2.5/src/project_agent/infrastructure/tasks/__init__.py +1 -0
  117. project_agent-0.2.5/src/project_agent/infrastructure/tasks/apply_runtime.py +720 -0
  118. project_agent-0.2.5/src/project_agent/infrastructure/tasks/backends.py +1759 -0
  119. project_agent-0.2.5/src/project_agent/infrastructure/tasks/factory.py +132 -0
  120. project_agent-0.2.5/src/project_agent/infrastructure/tasks/migration.py +52 -0
  121. project_agent-0.2.5/src/project_agent/infrastructure/tasks/task_group_project.py +134 -0
  122. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/interface/cli/app.py +16 -8
  123. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/interface/cli/commands/bootstrap.py +25 -0
  124. project_agent-0.2.5/src/project_agent/interface/cli/commands/context.py +553 -0
  125. project_agent-0.2.5/src/project_agent/interface/cli/commands/db.py +186 -0
  126. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/interface/cli/commands/doc.py +33 -29
  127. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/interface/cli/commands/doc_hub.py +98 -10
  128. project_agent-0.2.5/src/project_agent/interface/cli/commands/mind.py +321 -0
  129. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/interface/cli/commands/monitoring.py +14 -6
  130. project_agent-0.2.5/src/project_agent/interface/cli/commands/onboarding.py +35 -0
  131. project_agent-0.2.5/src/project_agent/interface/cli/commands/proposal.py +33 -0
  132. project_agent-0.2.5/src/project_agent/interface/cli/commands/query.py +59 -0
  133. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/interface/cli/commands/report.py +37 -6
  134. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/interface/cli/commands/scheduled.py +11 -5
  135. project_agent-0.2.5/src/project_agent/interface/cli/commands/sprint.py +52 -0
  136. project_agent-0.2.5/src/project_agent/interface/cli/commands/task.py +32 -0
  137. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/interface/cli/helptext.py +27 -13
  138. project_agent-0.2.5/src/project_agent/interface/cli/scene_transport.py +49 -0
  139. project_agent-0.2.5/src/project_agent/interface/cli/unauthorized.py +35 -0
  140. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent.egg-info/PKG-INFO +1 -1
  141. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent.egg-info/SOURCES.txt +108 -29
  142. project_agent-0.2.5/tests/test_actor_ref.py +35 -0
  143. project_agent-0.2.5/tests/test_bootstrap_apply.py +200 -0
  144. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_bootstrap_checkpoint.py +243 -91
  145. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_cli_help.py +129 -60
  146. project_agent-0.2.4/tests/test_cli_version.py → project_agent-0.2.5/tests/test_cli_sprint.py +17 -0
  147. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_context_add_project_member.py +1 -1
  148. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_context_project_binding.py +1 -1
  149. project_agent-0.2.5/tests/test_context_project_summary.py +1545 -0
  150. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_context_resolve_binding.py +1 -1
  151. project_agent-0.2.5/tests/test_context_resolve_user.py +129 -0
  152. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_context_search_user.py +13 -4
  153. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_context_set_project_owner.py +119 -4
  154. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_context_upsert_user_identity.py +79 -5
  155. project_agent-0.2.5/tests/test_core_relationships.py +1040 -0
  156. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_db_migration.py +4 -4
  157. project_agent-0.2.5/tests/test_db_rename_channel.py +230 -0
  158. project_agent-0.2.5/tests/test_db_schema.py +739 -0
  159. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_db_session.py +71 -0
  160. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_doc_hub.py +643 -42
  161. project_agent-0.2.5/tests/test_doc_render_planned_sprints.py +992 -0
  162. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_loop_jobs.py +68 -0
  163. project_agent-0.2.5/tests/test_mind_approval_policy.py +91 -0
  164. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_mind_read.py +566 -350
  165. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_monitoring_plan.py +1 -1
  166. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_monitoring_run.py +120 -12
  167. project_agent-0.2.5/tests/test_mushroom_prompt_hooks.py +704 -0
  168. project_agent-0.2.5/tests/test_onboarding_apply.py +310 -0
  169. project_agent-0.2.5/tests/test_onboarding_apply_cli.py +120 -0
  170. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_overview_sync_hints.py +33 -33
  171. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_project_group_boundary_guard.py +366 -307
  172. project_agent-0.2.5/tests/test_project_group_routing_contracts.py +209 -0
  173. project_agent-0.2.5/tests/test_proposal_apply.py +264 -0
  174. project_agent-0.2.5/tests/test_query_apply.py +986 -0
  175. project_agent-0.2.5/tests/test_query_cli.py +91 -0
  176. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_release_versioning.py +1 -1
  177. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_report_build.py +715 -131
  178. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_report_persistence.py +116 -45
  179. project_agent-0.2.5/tests/test_reporting_apply.py +106 -0
  180. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_runtime_bundles.py +128 -6
  181. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_runtime_output_hygiene_contracts.py +3 -2
  182. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_scheduled_run.py +436 -898
  183. project_agent-0.2.5/tests/test_sprint_apply.py +611 -0
  184. project_agent-0.2.5/tests/test_sprint_apply_cli.py +1205 -0
  185. project_agent-0.2.4/tests/test_version_closure_trigger.py → project_agent-0.2.5/tests/test_sprint_closure_trigger.py +229 -307
  186. project_agent-0.2.5/tests/test_sprint_rollover.py +349 -0
  187. project_agent-0.2.5/tests/test_sprint_rollover_cli.py +164 -0
  188. project_agent-0.2.4/tests/test_version_status_auto_sync.py → project_agent-0.2.5/tests/test_sprint_status_auto_sync.py +135 -98
  189. project_agent-0.2.5/tests/test_status_sensitive_task_reads.py +93 -0
  190. project_agent-0.2.5/tests/test_task_apply.py +1796 -0
  191. project_agent-0.2.5/tests/test_task_backend.py +3324 -0
  192. project_agent-0.2.5/tests/test_task_center_client.py +433 -0
  193. project_agent-0.2.5/tests/test_task_cli.py +497 -0
  194. project_agent-0.2.5/tests/test_task_migration.py +54 -0
  195. project_agent-0.2.5/tests/test_task_only_groups.py +845 -0
  196. project_agent-0.2.4/src/project_agent/application/context/get_project_owner.py +0 -53
  197. project_agent-0.2.4/src/project_agent/application/context/get_task.py +0 -15
  198. project_agent-0.2.4/src/project_agent/application/context/list_projects.py +0 -222
  199. project_agent-0.2.4/src/project_agent/application/context/list_tasks.py +0 -35
  200. project_agent-0.2.4/src/project_agent/application/context/set_project_owner.py +0 -59
  201. project_agent-0.2.4/src/project_agent/application/mind/planned_versions.py +0 -32
  202. project_agent-0.2.4/src/project_agent/application/mind/read.py +0 -340
  203. project_agent-0.2.4/src/project_agent/application/mind/signoff_proposal.py +0 -305
  204. project_agent-0.2.4/src/project_agent/application/mind/update_version.py +0 -260
  205. project_agent-0.2.4/src/project_agent/application/mind/write_task_update.py +0 -314
  206. project_agent-0.2.4/src/project_agent/application/version_closure/__init__.py +0 -3
  207. project_agent-0.2.4/src/project_agent/application/version_closure/evaluate.py +0 -86
  208. project_agent-0.2.4/src/project_agent/domain/shared/project_mind_derived.py +0 -143
  209. project_agent-0.2.4/src/project_agent/domain/version_closure/__init__.py +0 -13
  210. project_agent-0.2.4/src/project_agent/interface/cli/commands/context.py +0 -957
  211. project_agent-0.2.4/src/project_agent/interface/cli/commands/db.py +0 -28
  212. project_agent-0.2.4/src/project_agent/interface/cli/commands/mind.py +0 -1322
  213. project_agent-0.2.4/src/project_agent/interface/cli/commands/task_event_notify.py +0 -221
  214. project_agent-0.2.4/src/project_agent/interface/cli/commands/version_closure.py +0 -86
  215. project_agent-0.2.4/tests/test_context_get_project.py +0 -241
  216. project_agent-0.2.4/tests/test_context_get_project_owner.py +0 -203
  217. project_agent-0.2.4/tests/test_context_get_project_pending_states.py +0 -164
  218. project_agent-0.2.4/tests/test_context_list_projects.py +0 -635
  219. project_agent-0.2.4/tests/test_context_list_tasks.py +0 -475
  220. project_agent-0.2.4/tests/test_context_project_summary.py +0 -837
  221. project_agent-0.2.4/tests/test_db_schema.py +0 -380
  222. project_agent-0.2.4/tests/test_doc_render_planned_versions.py +0 -501
  223. project_agent-0.2.4/tests/test_finalize_version_closure.py +0 -848
  224. project_agent-0.2.4/tests/test_mind_governance.py +0 -1171
  225. project_agent-0.2.4/tests/test_mind_proposal_extensions.py +0 -768
  226. project_agent-0.2.4/tests/test_mind_proposal_signoff.py +0 -452
  227. project_agent-0.2.4/tests/test_project_group_routing_contracts.py +0 -173
  228. {project_agent-0.2.4 → project_agent-0.2.5}/README.md +0 -0
  229. {project_agent-0.2.4 → project_agent-0.2.5}/setup.cfg +0 -0
  230. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/__init__.py +0 -0
  231. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/__init__.py +0 -0
  232. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/bootstrap/__init__.py +0 -0
  233. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/context/__init__.py +0 -0
  234. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/context/add_project_member.py +0 -0
  235. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/context/binding_normalization.py +0 -0
  236. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/context/resolve_binding.py +0 -0
  237. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/context/resolve_group.py +0 -0
  238. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/doc/__init__.py +0 -0
  239. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/doc_hub/__init__.py +0 -0
  240. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/loop/__init__.py +0 -0
  241. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/mind/__init__.py +0 -0
  242. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/monitoring/__init__.py +0 -0
  243. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/monitoring/plan.py +0 -0
  244. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/report/__init__.py +0 -0
  245. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/scheduled/__init__.py +0 -0
  246. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/shared/project_participants.py +0 -0
  247. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/application/shared/user_refs.py +0 -0
  248. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/__init__.py +0 -0
  249. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/bootstrap/__init__.py +0 -0
  250. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/doc/__init__.py +0 -0
  251. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/doc_hub/__init__.py +0 -0
  252. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/loop/__init__.py +0 -0
  253. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/loop/models.py +0 -0
  254. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/mind/__init__.py +0 -0
  255. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/monitoring/__init__.py +0 -0
  256. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/project_context/__init__.py +0 -0
  257. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/report/__init__.py +0 -0
  258. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/scheduled/__init__.py +0 -0
  259. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/shared/__init__.py +0 -0
  260. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/shared/models.py +0 -0
  261. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/shared/project_participants.py +0 -0
  262. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/shared/user_refs.py +0 -0
  263. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/domain/user/__init__.py +0 -0
  264. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/infrastructure/__init__.py +0 -0
  265. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/infrastructure/clock/__init__.py +0 -0
  266. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/infrastructure/clock/workday_clock.py +0 -0
  267. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/infrastructure/db/__init__.py +0 -0
  268. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/infrastructure/db/migration.py +0 -0
  269. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/infrastructure/db/session.py +0 -0
  270. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/infrastructure/feature_flags.py +0 -0
  271. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/interface/__init__.py +0 -0
  272. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/interface/cli/__init__.py +0 -0
  273. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/interface/cli/commands/__init__.py +0 -0
  274. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/interface/cli/commands/_monitoring_support.py +0 -0
  275. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/interface/cli/commands/loop.py +0 -0
  276. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/interface/cli/commands/project_boundary.py +0 -0
  277. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent/interface/cli/commands/upgrade.py +0 -0
  278. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent.egg-info/dependency_links.txt +0 -0
  279. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent.egg-info/entry_points.txt +0 -0
  280. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent.egg-info/requires.txt +0 -0
  281. {project_agent-0.2.4 → project_agent-0.2.5}/src/project_agent.egg-info/top_level.txt +0 -0
  282. {project_agent-0.2.4 → project_agent-0.2.5}/tests/test_pending_state_idempotency.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: project-agent
3
- Version: 0.2.4
3
+ Version: 0.2.5
4
4
  Summary: Project Agent Python CLI core
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: typer<1,>=0.12
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "project-agent"
7
- version = "0.2.4"
7
+ version = "0.2.5"
8
8
  description = "Project Agent Python CLI core"
9
9
  requires-python = ">=3.11"
10
10
  dependencies = [
@@ -18,6 +18,8 @@ dependencies = [
18
18
 
19
19
  [dependency-groups]
20
20
  dev = [
21
+ "fastapi>=0.115,<1",
22
+ "httpx>=0.27,<1",
21
23
  "pytest>=8.0",
22
24
  ]
23
25
 
@@ -0,0 +1,222 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Protocol
4
+
5
+ from project_agent.application.bootstrap.contracts import (
6
+ BootstrapAcknowledgement,
7
+ BootstrapDraft,
8
+ BootstrapRequest,
9
+ )
10
+ from project_agent.application.shared.actor import ActorRef, ActorResolution
11
+ from project_agent.application.shared.scene_command import (
12
+ SceneError,
13
+ SceneOperationReceipt,
14
+ SceneReceipt,
15
+ )
16
+
17
+
18
+ class BootstrapRuntime(Protocol):
19
+ def resolve_actor(self, actor_ref: ActorRef) -> ActorResolution: ...
20
+
21
+ def init(self, project_id: str, bootstrap: BootstrapDraft) -> dict[str, Any]: ...
22
+
23
+ def mark(self, project_id: str, milestone: str) -> None: ...
24
+
25
+ def record_result(
26
+ self,
27
+ project_id: str,
28
+ acknowledgement: BootstrapAcknowledgement,
29
+ ) -> None: ...
30
+
31
+ def loop_state(
32
+ self,
33
+ project_id: str,
34
+ stuck_threshold: int,
35
+ ) -> dict[str, Any]: ...
36
+
37
+ def commit(self) -> None: ...
38
+
39
+ def rollback(self) -> None: ...
40
+
41
+
42
+ class BootstrapApply:
43
+ """Combine init/acknowledgement, ledger update and the next checkpoint read."""
44
+
45
+ _LEGACY_DOC_ACTIONS = {"land_project_card", "backfill_docs"}
46
+
47
+ def __init__(self, *, runtime: BootstrapRuntime) -> None:
48
+ self._runtime = runtime
49
+
50
+ def apply(self, request: BootstrapRequest) -> SceneReceipt:
51
+ init_result = None
52
+ changed = False
53
+ try:
54
+ if request.action == "init":
55
+ bootstrap, identity_error = self._resolve_bootstrap_people(
56
+ request.bootstrap
57
+ )
58
+ if identity_error is not None:
59
+ return SceneReceipt(
60
+ status="failed",
61
+ results=[
62
+ SceneOperationReceipt(
63
+ operation_id=request.operation_id,
64
+ action=request.action,
65
+ status="failed",
66
+ error=identity_error,
67
+ )
68
+ ],
69
+ )
70
+ init_result = self._runtime.init(request.project_id, bootstrap)
71
+ changed = True
72
+ if request.acknowledgement is not None:
73
+ acknowledgement = request.acknowledgement
74
+ if acknowledgement.milestone is not None:
75
+ self._runtime.mark(request.project_id, acknowledgement.milestone)
76
+ if acknowledgement.next_action is not None:
77
+ self._runtime.record_result(request.project_id, acknowledgement)
78
+ changed = True
79
+
80
+ loop_state = self._runtime.loop_state(
81
+ request.project_id,
82
+ request.stuck_threshold,
83
+ )
84
+ for _ in range(2):
85
+ next_action = self._next_action(loop_state)
86
+ if next_action not in self._LEGACY_DOC_ACTIONS:
87
+ break
88
+ self._runtime.record_result(
89
+ request.project_id,
90
+ BootstrapAcknowledgement(
91
+ next_action=next_action,
92
+ outcome="skipped",
93
+ reason="document_refresh_requires_user_request",
94
+ ),
95
+ )
96
+ changed = True
97
+ loop_state = self._runtime.loop_state(
98
+ request.project_id,
99
+ request.stuck_threshold,
100
+ )
101
+ self._runtime.commit()
102
+ except Exception as exc:
103
+ self._runtime.rollback()
104
+ return SceneReceipt(
105
+ status="failed",
106
+ results=[
107
+ SceneOperationReceipt(
108
+ operation_id=request.operation_id,
109
+ action=request.action,
110
+ status="failed",
111
+ error=SceneError(
112
+ code="bootstrap_apply_failed",
113
+ message=str(exc),
114
+ retryable=True,
115
+ next_action="retry",
116
+ ),
117
+ )
118
+ ],
119
+ )
120
+
121
+ if loop_state.get("status") == "not_found":
122
+ return SceneReceipt(
123
+ status="failed",
124
+ results=[
125
+ SceneOperationReceipt(
126
+ operation_id=request.operation_id,
127
+ action=request.action,
128
+ status="failed",
129
+ error=SceneError(
130
+ code="project_not_found",
131
+ message=f"Project not found: {request.project_id}",
132
+ ),
133
+ )
134
+ ],
135
+ )
136
+ return SceneReceipt(
137
+ status="ok",
138
+ results=[
139
+ SceneOperationReceipt(
140
+ operation_id=request.operation_id,
141
+ action=request.action,
142
+ status="applied" if changed else "unchanged",
143
+ data={
144
+ **({"bootstrap": init_result} if init_result is not None else {}),
145
+ "loopState": loop_state,
146
+ "nextEffect": self._next_effect(loop_state),
147
+ },
148
+ )
149
+ ],
150
+ )
151
+
152
+ def _resolve_bootstrap_people(
153
+ self,
154
+ bootstrap: BootstrapDraft,
155
+ ) -> tuple[BootstrapDraft, SceneError | None]:
156
+ owner_user_id = bootstrap.owner_user_id
157
+ if bootstrap.owner_ref is not None:
158
+ resolution = self._runtime.resolve_actor(bootstrap.owner_ref)
159
+ if resolution.status != "resolved" or not resolution.user_id:
160
+ return bootstrap, SceneError(
161
+ code=f"bootstrap_owner_identity_{resolution.status}",
162
+ message=f"Bootstrap owner identity is {resolution.status}",
163
+ )
164
+ owner_user_id = resolution.user_id
165
+
166
+ participant_user_ids = list(bootstrap.participant_user_ids)
167
+ for participant_ref in bootstrap.participant_refs:
168
+ resolution = self._runtime.resolve_actor(participant_ref)
169
+ if resolution.status != "resolved" or not resolution.user_id:
170
+ return bootstrap, SceneError(
171
+ code=f"bootstrap_participant_identity_{resolution.status}",
172
+ message=f"Bootstrap participant identity is {resolution.status}",
173
+ )
174
+ participant_user_ids.append(resolution.user_id)
175
+
176
+ return (
177
+ bootstrap.model_copy(
178
+ update={
179
+ "owner_user_id": owner_user_id,
180
+ "owner_ref": None,
181
+ "participant_user_ids": participant_user_ids,
182
+ "participant_refs": [],
183
+ }
184
+ ),
185
+ None,
186
+ )
187
+
188
+ @staticmethod
189
+ def _next_action(loop_state: dict[str, Any]) -> str | None:
190
+ return (loop_state.get("checkpoint") or {}).get("nextAction")
191
+
192
+ @classmethod
193
+ def _next_effect(cls, loop_state: dict[str, Any]) -> dict[str, Any]:
194
+ checkpoint = loop_state.get("checkpoint") or {}
195
+ next_action = checkpoint.get("nextAction")
196
+ if loop_state.get("status") == "blocked":
197
+ return {
198
+ "action": "report_blocker",
199
+ "blocker": loop_state.get("blocker"),
200
+ }
201
+ if next_action == "create_group_binding":
202
+ return {"action": "create_project_group_binding"}
203
+ if next_action == "send_alignment_intro":
204
+ return {
205
+ "action": "send_template",
206
+ "template": "group-alignment-intro.md",
207
+ }
208
+ if next_action == "collect_alignment_fields":
209
+ return {
210
+ "action": "request_alignment_fields",
211
+ "fields": checkpoint.get("alignmentGaps") or [],
212
+ }
213
+ if next_action == "send_execution_confirmation":
214
+ return {
215
+ "action": "send_template",
216
+ "template": "execution-start-confirmation.md",
217
+ }
218
+ if next_action == "await_owner_confirmation":
219
+ return {"action": "await_owner_confirmation"}
220
+ if next_action == "bootstrap_complete":
221
+ return {"action": "complete"}
222
+ return {"action": "stop"}
@@ -9,8 +9,8 @@ from project_agent.domain.bootstrap.models import (
9
9
  )
10
10
  from project_agent.domain.shared.project_mind_derived import (
11
11
  describe_missing_task_fields,
12
- describe_missing_version_fields,
13
- resolve_current_version,
12
+ describe_missing_sprint_fields,
13
+ resolve_current_sprint,
14
14
  )
15
15
 
16
16
  MILESTONE_ALIGNMENT_INTRO = "alignment_intro_sent"
@@ -31,7 +31,7 @@ class BootstrapReadStore(Protocol):
31
31
 
32
32
  def list_bindings_by_project_id(self, project_id: str) -> list[Any]: ...
33
33
 
34
- def list_versions_by_project_id(self, project_id: str) -> list[Any]: ...
34
+ def list_sprints_by_project_id(self, project_id: str) -> list[Any]: ...
35
35
 
36
36
  def list_tasks_by_project_id(self, project_id: str) -> list[Any]: ...
37
37
 
@@ -115,10 +115,10 @@ def evaluate_bootstrap_checkpoint(
115
115
  has_project_card_doc = "project_card" in landed_doc_kinds
116
116
  doc_gaps = [kind for kind in REQUIRED_BOOTSTRAP_DOC_KINDS if kind not in landed_doc_kinds]
117
117
 
118
- versions = bootstrap_store.list_versions_by_project_id(project_id)
118
+ sprints = bootstrap_store.list_sprints_by_project_id(project_id)
119
119
  tasks = bootstrap_store.list_tasks_by_project_id(project_id)
120
- alignment_gaps = _build_alignment_gaps(project=project, versions=versions, tasks=tasks)
121
- alignment_ready = _is_alignment_ready(project=project, versions=versions, tasks=tasks)
120
+ alignment_gaps = _build_alignment_gaps(project=project, sprints=sprints, tasks=tasks)
121
+ alignment_ready = _is_alignment_ready(project=project, sprints=sprints, tasks=tasks)
122
122
 
123
123
  mind_stage = project.get("mind_stage") or "v0"
124
124
  kickoff_sent = _is_milestone_marked(
@@ -126,7 +126,7 @@ def evaluate_bootstrap_checkpoint(
126
126
  state_key=kickoff_state_key(project_id),
127
127
  pending_state_store=pending_state_store,
128
128
  )
129
- # bootstrap 是否仍在进行,以 kickoff 是否已落账为准:create-version 会在团队对齐期
129
+ # bootstrap 是否仍在进行,以 kickoff 是否已落账为准:Sprint scene 创建会在团队对齐期
130
130
  # 把 mind_stage 提前翻成 v1,但只要 kickoff 还没发,bootstrap 就还没结束。
131
131
  bootstrap_active = not kickoff_sent
132
132
 
@@ -164,8 +164,6 @@ def evaluate_bootstrap_checkpoint(
164
164
  next_action=_select_next_action(
165
165
  bootstrap_active=bootstrap_active,
166
166
  has_group_binding=has_group_binding,
167
- has_project_card_doc=has_project_card_doc,
168
- doc_gaps=doc_gaps,
169
167
  intro_status=intro_status,
170
168
  alignment_ready=alignment_ready,
171
169
  confirmation_status=confirmation_status,
@@ -231,17 +229,17 @@ def mark_bootstrap_milestone(
231
229
 
232
230
 
233
231
  def _build_alignment_gaps(
234
- *, project: dict, versions: list[dict], tasks: list[dict]
232
+ *, project: dict, sprints: list[dict], tasks: list[dict]
235
233
  ) -> list[str]:
236
- current_version = resolve_current_version(project=project, versions=versions)
237
- if current_version is None:
238
- return ["missing_current_version"]
234
+ current_sprint = resolve_current_sprint(project=project, sprints=sprints)
235
+ if current_sprint is None:
236
+ return ["missing_current_sprint"]
239
237
  current_tasks = [
240
- task for task in tasks if task.get("version_id") == current_version.get("version_id")
238
+ task for task in tasks if task.get("sprint_id") == current_sprint.get("sprint_id")
241
239
  ]
242
240
  gaps = [
243
- f"current_version:{field}"
244
- for field in describe_missing_version_fields(version=current_version, tasks=current_tasks)
241
+ f"current_sprint:{field}"
242
+ for field in describe_missing_sprint_fields(sprint=current_sprint, tasks=current_tasks)
245
243
  ]
246
244
  if not current_tasks:
247
245
  gaps.append("missing_trackable_task")
@@ -252,14 +250,14 @@ def _build_alignment_gaps(
252
250
  return gaps
253
251
 
254
252
 
255
- def _is_alignment_ready(*, project: dict, versions: list[dict], tasks: list[dict]) -> bool:
256
- current_version = resolve_current_version(project=project, versions=versions)
257
- if current_version is None:
253
+ def _is_alignment_ready(*, project: dict, sprints: list[dict], tasks: list[dict]) -> bool:
254
+ current_sprint = resolve_current_sprint(project=project, sprints=sprints)
255
+ if current_sprint is None:
258
256
  return False
259
257
  current_tasks = [
260
- task for task in tasks if task.get("version_id") == current_version.get("version_id")
258
+ task for task in tasks if task.get("sprint_id") == current_sprint.get("sprint_id")
261
259
  ]
262
- if describe_missing_version_fields(version=current_version, tasks=current_tasks):
260
+ if describe_missing_sprint_fields(sprint=current_sprint, tasks=current_tasks):
263
261
  return False
264
262
  # 执行启动确认只要求至少一个可追踪 Task 必填字段齐全。
265
263
  return any(not describe_missing_task_fields(task=task) for task in current_tasks)
@@ -345,8 +343,6 @@ def _select_next_action(
345
343
  *,
346
344
  bootstrap_active: bool,
347
345
  has_group_binding: bool,
348
- has_project_card_doc: bool,
349
- doc_gaps: list[str],
350
346
  intro_status: str,
351
347
  alignment_ready: bool,
352
348
  confirmation_status: str,
@@ -355,20 +351,15 @@ def _select_next_action(
355
351
  return "bootstrap_complete"
356
352
  if not has_group_binding:
357
353
  return "create_group_binding"
358
- # 对齐引导唯一硬前置是 Project Card;缺它先驱动文档落地。
359
- if intro_status == "pending" and not has_project_card_doc:
360
- return "land_project_card"
361
354
  if intro_status == "pending":
362
355
  return "send_alignment_intro"
363
356
  if confirmation_status == "pending":
364
357
  return "send_execution_confirmation"
365
- # 消息欠账还清后,剩余文档欠账由 agent 当轮补齐,不阻塞人侧流程。
366
- if doc_gaps:
367
- return "backfill_docs"
368
358
  if not alignment_ready:
369
359
  return "collect_alignment_fields"
370
360
  if confirmation_status == "sent":
371
361
  return "await_owner_confirmation"
362
+ # 文档缺口只保留为待更新提示,不进入 bootstrap action 选择。
372
363
  return "collect_alignment_fields"
373
364
 
374
365
 
@@ -0,0 +1,80 @@
1
+ from typing import Any, Literal
2
+
3
+ from pydantic import Field, model_validator
4
+
5
+ from project_agent.application.shared.actor import ActorRef
6
+ from project_agent.domain.shared.models import ProjectAgentModel
7
+
8
+
9
+ class BootstrapDraft(ProjectAgentModel):
10
+ project_name: str
11
+ owner_user_id: str | None = None
12
+ owner_ref: ActorRef | None = None
13
+ primary_goal: str
14
+ target_release_date: str | None = None
15
+ timezone: str = "Asia/Shanghai"
16
+ channel: str | None = None
17
+ project_group_id: str | None = None
18
+ participant_user_ids: list[str] = Field(default_factory=list)
19
+ participant_refs: list[ActorRef] = Field(default_factory=list)
20
+
21
+ @model_validator(mode="after")
22
+ def validate_people_references(self) -> "BootstrapDraft":
23
+ if (self.owner_user_id is None) == (self.owner_ref is None):
24
+ raise ValueError(
25
+ "bootstrap requires exactly one ownerUserId or ownerRef"
26
+ )
27
+ if self.participant_user_ids and self.participant_refs:
28
+ raise ValueError(
29
+ "bootstrap accepts participantUserIds or participantRefs, not both"
30
+ )
31
+ return self
32
+
33
+
34
+ class BootstrapAcknowledgement(ProjectAgentModel):
35
+ next_action: Literal[
36
+ "create_group_binding",
37
+ "land_project_card",
38
+ "send_alignment_intro",
39
+ "backfill_docs",
40
+ "collect_alignment_fields",
41
+ "send_execution_confirmation",
42
+ ] | None = None
43
+ outcome: Literal["success", "failed", "skipped"] | None = None
44
+ milestone: Literal[
45
+ "alignment_intro_sent",
46
+ "execution_confirmation_sent",
47
+ "kickoff_sent",
48
+ ] | None = None
49
+ stage: str | None = None
50
+ reason: str | None = None
51
+ details: dict[str, Any] = Field(default_factory=dict)
52
+
53
+ @model_validator(mode="after")
54
+ def validate_result_pair(self) -> "BootstrapAcknowledgement":
55
+ if (self.next_action is None) != (self.outcome is None):
56
+ raise ValueError("nextAction and outcome must be provided together")
57
+ if self.next_action is None and self.milestone is None:
58
+ raise ValueError("acknowledgement requires a loop result or milestone")
59
+ return self
60
+
61
+
62
+ class BootstrapRequest(ProjectAgentModel):
63
+ operation_id: str
64
+ action: Literal["init", "advance"]
65
+ project_id: str
66
+ bootstrap: BootstrapDraft | None = None
67
+ acknowledgement: BootstrapAcknowledgement | None = None
68
+ stuck_threshold: int = 3
69
+
70
+ @model_validator(mode="after")
71
+ def validate_action_fields(self) -> "BootstrapRequest":
72
+ if not self.operation_id:
73
+ raise ValueError("operationId must be non-empty")
74
+ if self.action == "init" and self.bootstrap is None:
75
+ raise ValueError("init requires bootstrap")
76
+ if self.action == "advance" and self.bootstrap is not None:
77
+ raise ValueError("advance does not accept bootstrap")
78
+ if self.stuck_threshold < 1:
79
+ raise ValueError("stuckThreshold must be at least 1")
80
+ return self
@@ -13,7 +13,7 @@ from project_agent.domain.bootstrap.models import BootstrapBinding, BootstrapIni
13
13
  from project_agent.domain.shared.project_mind_derived import (
14
14
  build_project_intro,
15
15
  collect_participants,
16
- resolve_current_version,
16
+ resolve_current_sprint,
17
17
  resolve_target_release_date,
18
18
  )
19
19
  from project_agent.domain.shared.project_mind_readiness import (
@@ -31,7 +31,7 @@ class BootstrapStore(Protocol):
31
31
 
32
32
  def list_bindings_by_project_id(self, project_id: str) -> list[Any]: ...
33
33
 
34
- def list_versions_by_project_id(self, project_id: str) -> list[Any]: ...
34
+ def list_sprints_by_project_id(self, project_id: str) -> list[Any]: ...
35
35
 
36
36
  def list_tasks_by_project_id(self, project_id: str) -> list[Any]: ...
37
37
 
@@ -70,7 +70,7 @@ def init_project_bootstrap(
70
70
  "mind_stage": (existing_project or {}).get("mind_stage") or "v0",
71
71
  "lifecycle_status": (existing_project or {}).get("lifecycle_status") or "active",
72
72
  "current_revision_id": (existing_project or {}).get("current_revision_id"),
73
- "current_version_id": (existing_project or {}).get("current_version_id"),
73
+ "current_sprint_id": (existing_project or {}).get("current_sprint_id"),
74
74
  "target_release_date": target_release_date
75
75
  if target_release_date is not None
76
76
  else (existing_project or {}).get("target_release_date"),
@@ -134,12 +134,12 @@ def init_project_bootstrap(
134
134
  )
135
135
  for binding in bootstrap_store.list_bindings_by_project_id(project_id)
136
136
  ]
137
- versions = bootstrap_store.list_versions_by_project_id(project_id)
137
+ sprints = bootstrap_store.list_sprints_by_project_id(project_id)
138
138
  tasks = bootstrap_store.list_tasks_by_project_id(project_id)
139
139
  stored_participants = bootstrap_store.list_participants_by_project_id(project_id)
140
140
  readiness_participants = [
141
141
  *stored_participants,
142
- *_participant_rows_from_project_mind(versions=versions, tasks=tasks),
142
+ *_participant_rows_from_project_mind(sprints=sprints, tasks=tasks),
143
143
  ]
144
144
  documents = bootstrap_store.list_documents_by_project_id(project_id)
145
145
  monitoring_policy = bootstrap_store.find_monitoring_policy_by_project_id(project_id)
@@ -152,11 +152,11 @@ def init_project_bootstrap(
152
152
  bindings=[binding.model_dump(mode="json", by_alias=False) for binding in bindings],
153
153
  monitoring_enabled=bool((monitoring_policy or {}).get("enabled")),
154
154
  documents=documents,
155
- versions=versions,
155
+ sprints=sprints,
156
156
  tasks=tasks,
157
157
  participants=readiness_participants,
158
158
  )
159
- current_version = resolve_current_version(project=project, versions=versions)
159
+ current_sprint = resolve_current_sprint(project=project, sprints=sprints)
160
160
 
161
161
  return BootstrapInitResult(
162
162
  project_id=project["project_id"],
@@ -165,14 +165,14 @@ def init_project_bootstrap(
165
165
  primary_goal=project.get("primary_goal") or "",
166
166
  target_release_date=resolve_target_release_date(
167
167
  project=project,
168
- current_version=current_version,
168
+ current_sprint=current_sprint,
169
169
  ),
170
170
  participants=collect_participants(
171
- versions=versions,
171
+ sprints=sprints,
172
172
  tasks=tasks,
173
173
  participants=stored_participants,
174
174
  ),
175
- project_intro=build_project_intro(project=project, versions=versions, tasks=tasks),
175
+ project_intro=build_project_intro(project=project, sprints=sprints, tasks=tasks),
176
176
  last_updated_at=project.get("last_updated_at"),
177
177
  mind_stage=project["mind_stage"],
178
178
  lifecycle_status=project["lifecycle_status"],
@@ -194,8 +194,8 @@ def _dedupe_participant_user_ids(values: list[str]) -> list[str]:
194
194
  return ordered
195
195
 
196
196
 
197
- def _participant_rows_from_project_mind(*, versions: list[dict], tasks: list[dict]) -> list[dict]:
197
+ def _participant_rows_from_project_mind(*, sprints: list[dict], tasks: list[dict]) -> list[dict]:
198
198
  return [
199
199
  {"user_id": user_id, "status": "active"}
200
- for user_id in collect_participants(versions=versions, tasks=tasks)
200
+ for user_id in collect_participants(sprints=sprints, tasks=tasks)
201
201
  ]
@@ -17,7 +17,7 @@ class BootstrapReadStore(Protocol):
17
17
 
18
18
  def list_bindings_by_project_id(self, project_id: str) -> list[Any]: ...
19
19
 
20
- def list_versions_by_project_id(self, project_id: str) -> list[Any]: ...
20
+ def list_sprints_by_project_id(self, project_id: str) -> list[Any]: ...
21
21
 
22
22
  def list_tasks_by_project_id(self, project_id: str) -> list[Any]: ...
23
23