openfactory 0.4.0__tar.gz → 0.4.2__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 (998) hide show
  1. {openfactory-0.4.0/openfactory.egg-info → openfactory-0.4.2}/PKG-INFO +1 -1
  2. {openfactory-0.4.0 → openfactory-0.4.2}/README.md +1 -1
  3. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/__init__.py +1 -1
  4. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/actions/catalog.py +378 -36
  5. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/base.py +10 -0
  6. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/kimi.py +4 -2
  7. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/roles.py +3 -0
  8. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/azure_devops.py +159 -59
  9. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board_db.py +25 -3
  10. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/credential/registry.py +86 -13
  11. openfactory-0.4.2/openfactory/adapters/credential/short_lived.py +69 -0
  12. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/sandbox/container.py +108 -0
  13. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/sandbox/worktree.py +17 -3
  14. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/base.py +107 -0
  15. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/local.py +86 -0
  16. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/api/app.py +51 -6
  17. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/api/panel.html +245 -43
  18. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/api/product_chat.py +45 -12
  19. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/box_prove.py +52 -0
  20. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/cli.py +9 -1
  21. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/project.py +5 -0
  22. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/ticket.py +5 -0
  23. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/credentials.py +170 -3
  24. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/doctor.py +226 -4
  25. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/factory.py +10 -3
  26. openfactory-0.4.2/openfactory/gate_seal.py +150 -0
  27. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/memory/transcript.py +71 -2
  28. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/observability/metrics.py +3 -0
  29. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/deployment.py +33 -2
  30. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/orchestrator/context.py +90 -0
  31. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/orchestrator/machine.py +24 -5
  32. openfactory-0.4.2/openfactory/org_defaults/cards/defect-template.md +23 -0
  33. openfactory-0.4.2/openfactory/org_defaults/cards/rubric.yaml +140 -0
  34. openfactory-0.4.2/openfactory/org_defaults/cards/template.md +23 -0
  35. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/__init__.py +2 -1
  36. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/demand.py +51 -5
  37. openfactory-0.4.2/openfactory/preview/live.py +179 -0
  38. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/siblings.py +7 -4
  39. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/steps.py +3 -3
  40. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/agenda.py +42 -20
  41. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/attachments.py +48 -16
  42. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/authoring.py +31 -9
  43. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/board.py +35 -1
  44. openfactory-0.4.2/openfactory/product/cards.py +888 -0
  45. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/case.py +21 -3
  46. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/confirm.py +40 -4
  47. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/door.py +6 -2
  48. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/engine.py +288 -46
  49. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/events.py +171 -27
  50. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/model.py +14 -8
  51. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/module.py +333 -44
  52. openfactory-0.4.2/openfactory/product/progress.py +73 -0
  53. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/role.py +94 -52
  54. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/voice.py +450 -6
  55. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/review/verdict.py +17 -7
  56. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/boxed_job.py +25 -2
  57. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/repo_cache.py +202 -66
  58. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/activities.py +473 -37
  59. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/conversation.py +67 -10
  60. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/io.py +50 -0
  61. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/view.py +54 -4
  62. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/worker.py +12 -1
  63. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/workflow.py +164 -16
  64. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/techlead/conversation.py +7 -1
  65. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/techlead/voice.py +44 -0
  66. {openfactory-0.4.0 → openfactory-0.4.2/openfactory.egg-info}/PKG-INFO +1 -1
  67. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory.egg-info/SOURCES.txt +25 -0
  68. {openfactory-0.4.0 → openfactory-0.4.2}/pyproject.toml +1 -1
  69. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_card_is_closed_only_when_its_work_merges.py +3 -2
  70. openfactory-0.4.2/tests/test_a_card_is_drafted_and_judged_before_the_yes.py +1010 -0
  71. openfactory-0.4.2/tests/test_a_card_nobody_started_can_be_closed_and_removed.py +573 -0
  72. openfactory-0.4.2/tests/test_a_clicked_yes_is_answered_once.py +316 -0
  73. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_credential_is_scoped.py +2 -0
  74. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_credential_only_goes_to_its_own_host.py +90 -3
  75. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_deployments_addresses_have_one_owner.py +2 -1
  76. openfactory-0.4.2/tests/test_a_failed_preview_is_said_on_the_card.py +265 -0
  77. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_file_is_attached_in_the_conversation.py +132 -2
  78. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_forge_that_brings_its_own_credential_is_not_reported_as_having_none.py +1 -1
  79. openfactory-0.4.2/tests/test_a_gate_answer_needs_the_panels_seal.py +243 -0
  80. openfactory-0.4.2/tests/test_a_hosted_worker_uses_the_identity_its_host_has.py +463 -0
  81. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_large_prompt_travels_off_the_command_line.py +31 -0
  82. openfactory-0.4.2/tests/test_a_malfunction_is_a_defect_without_a_written_promise.py +63 -0
  83. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_preview_is_started_on_demand.py +27 -2
  84. openfactory-0.4.2/tests/test_a_preview_starts_itself_when_the_pull_request_opens.py +601 -0
  85. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_product_is_previewed_across_its_repositories.py +3 -2
  86. openfactory-0.4.2/tests/test_a_proxy_is_not_the_metadata_endpoint.py +265 -0
  87. openfactory-0.4.2/tests/test_a_pull_request_lives_in_the_forges_repository.py +253 -0
  88. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_re_run_keeps_every_value_the_file_holds.py +27 -0
  89. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_refusal_is_not_an_answer.py +3 -1
  90. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_rejected_review_can_be_asked_again.py +1 -1
  91. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_resume_re_enters_the_merge.py +7 -6
  92. openfactory-0.4.2/tests/test_a_retried_turn_records_the_message_once.py +282 -0
  93. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_stream_ends_when_its_credential_does.py +23 -3
  94. openfactory-0.4.2/tests/test_a_test_leaves_the_environment_as_it_found_it.py +57 -0
  95. openfactory-0.4.2/tests/test_a_turn_says_what_it_is_doing_while_the_person_waits.py +501 -0
  96. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_vendor_error_code_is_not_a_status.py +4 -1
  97. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_accepting_what_the_code_already_does_files_nothing.py +11 -5
  98. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_card_maintenance.py +1 -1
  99. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_corpus_health_and_board_placement.py +1 -1
  100. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_events_and_the_agenda.py +28 -8
  101. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_every_source_is_mounted.py +153 -0
  102. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_everyone_who_opens_a_door_asks_the_one_gate.py +8 -2
  103. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_no_unbounded_growth.py +11 -0
  104. openfactory-0.4.2/tests/test_nothing_is_published_beyond_this_machine.py +65 -0
  105. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_only_a_blocking_build_failure_is_broken_code.py +4 -3
  106. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_repo_cache_lifecycle.py +104 -0
  107. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_sweep_client_surface.py +7 -1
  108. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_temporal_workflow.py +126 -7
  109. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_action_layer.py +7 -0
  110. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_ado_credential_outlives_one_token.py +7 -7
  111. openfactory-0.4.2/tests/test_the_board_a_reader_sees_is_the_board_on_disk.py +256 -0
  112. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_board_is_a_page_on_the_panel.py +10 -11
  113. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_deployment_asks_the_rows_for_their_variables.py +2 -1
  114. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_forge_credential_is_per_project.py +24 -5
  115. openfactory-0.4.2/tests/test_the_inlined_document_bytes_are_reported.py +243 -0
  116. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_installer_builds_the_commands_it_says_it_does.py +98 -4
  117. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_merge_gate_is_heard_on_every_path.py +86 -9
  118. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_merge_is_the_end_of_the_road.py +3 -2
  119. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_one_door.py +1 -1
  120. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_one_machine_deployment_runs_unattended.py +16 -0
  121. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_oss_distribution.py +15 -0
  122. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_is_a_chat.py +9 -3
  123. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_owner_opens_a_card_as_described.py +1 -1
  124. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_role_lives_outside_slack.py +7 -2
  125. openfactory-0.4.2/tests/test_the_requester_hears_the_change_is_theirs_to_try.py +424 -0
  126. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_suite_runs_where_a_maintainer_sits.py +32 -6
  127. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_techlead_can_see_what_it_reasons_about.py +1 -0
  128. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_web_offers_the_room_and_the_private_chat.py +3 -1
  129. {openfactory-0.4.0 → openfactory-0.4.2}/LICENSE +0 -0
  130. {openfactory-0.4.0 → openfactory-0.4.2}/NOTICE +0 -0
  131. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/actions/__init__.py +0 -0
  132. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/actions/base.py +0 -0
  133. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/actions/floor_intents.py +0 -0
  134. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/__init__.py +0 -0
  135. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/__init__.py +0 -0
  136. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/claude_code.py +0 -0
  137. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/codex.py +0 -0
  138. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/opencode.py +0 -0
  139. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/registry.py +0 -0
  140. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/routes.py +0 -0
  141. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/session_store.py +0 -0
  142. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/stream.py +0 -0
  143. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/techlead.py +0 -0
  144. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/token_pool.py +0 -0
  145. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board/__init__.py +0 -0
  146. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board/azure_devops.py +0 -0
  147. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board/base.py +0 -0
  148. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board/columns.py +0 -0
  149. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board/factory.py +0 -0
  150. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board/jira.py +0 -0
  151. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board/local.py +0 -0
  152. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board_setup/__init__.py +0 -0
  153. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board_setup/base.py +0 -0
  154. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board_setup/local.py +0 -0
  155. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board_setup/registry.py +0 -0
  156. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/channel/__init__.py +0 -0
  157. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/channel/base.py +0 -0
  158. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/channel/panel.py +0 -0
  159. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/channel/registry.py +0 -0
  160. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/credential/__init__.py +0 -0
  161. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/embed/__init__.py +0 -0
  162. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/embed/base.py +0 -0
  163. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/embed/local.py +0 -0
  164. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/embed/registry.py +0 -0
  165. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/environment/__init__.py +0 -0
  166. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/environment/azure_pipelines.py +0 -0
  167. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/environment/base.py +0 -0
  168. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/environment/github_actions.py +0 -0
  169. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/environment/none.py +0 -0
  170. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/environment/registry.py +0 -0
  171. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/__init__.py +0 -0
  172. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/base.py +0 -0
  173. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/mail.py +0 -0
  174. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/markup.py +0 -0
  175. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/model.py +0 -0
  176. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/office.py +0 -0
  177. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/pdf.py +0 -0
  178. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/registry.py +0 -0
  179. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/text.py +0 -0
  180. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/vision.py +0 -0
  181. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/forge/__init__.py +0 -0
  182. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/forge/azure_devops.py +0 -0
  183. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/forge/base.py +0 -0
  184. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/forge/github.py +0 -0
  185. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/forge/local.py +0 -0
  186. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/forge/registry.py +0 -0
  187. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/github_app.py +0 -0
  188. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/notify/__init__.py +0 -0
  189. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/notify/base.py +0 -0
  190. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/notify/panel.py +0 -0
  191. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/notify/registry.py +0 -0
  192. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/preview/__init__.py +0 -0
  193. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/preview/base.py +0 -0
  194. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/preview/compose.py +0 -0
  195. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/preview/none.py +0 -0
  196. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/preview/registry.py +0 -0
  197. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/reviewer/__init__.py +0 -0
  198. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/reviewer/base.py +0 -0
  199. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/reviewer/claude_code.py +0 -0
  200. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/reviewer/harness.py +0 -0
  201. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/sandbox/__init__.py +0 -0
  202. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/sandbox/base.py +0 -0
  203. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/sandbox/registry.py +0 -0
  204. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/sandbox/timeouts.py +0 -0
  205. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/__init__.py +0 -0
  206. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/azure_devops.py +0 -0
  207. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/github.py +0 -0
  208. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/github_board_setup.py +0 -0
  209. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/github_project.py +0 -0
  210. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/jira.py +0 -0
  211. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/parse.py +0 -0
  212. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/registry.py +0 -0
  213. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/after_merge.py +0 -0
  214. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/agent_answer.py +0 -0
  215. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/api/__init__.py +0 -0
  216. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/api/metrics_view.py +0 -0
  217. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/approvals.py +0 -0
  218. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/cli_refusals.py +0 -0
  219. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/conformance/__init__.py +0 -0
  220. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/conformance/adapters.py +0 -0
  221. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/__init__.py +0 -0
  222. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/aliases.py +0 -0
  223. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/bot.py +0 -0
  224. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/checks.py +0 -0
  225. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/commands.py +0 -0
  226. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/decision.py +0 -0
  227. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/document.py +0 -0
  228. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/item_space.py +0 -0
  229. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/manifest.py +0 -0
  230. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/product.py +0 -0
  231. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/profile.py +0 -0
  232. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/refs.py +0 -0
  233. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/review.py +0 -0
  234. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/run.py +0 -0
  235. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/state.py +0 -0
  236. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/doors.py +0 -0
  237. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/environ.py +0 -0
  238. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/floor/__init__.py +0 -0
  239. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/floor/ladder.py +0 -0
  240. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/floor/reading.py +0 -0
  241. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/identity/__init__.py +0 -0
  242. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/identity/base.py +0 -0
  243. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/identity/local.py +0 -0
  244. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/identity/oidc.py +0 -0
  245. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/identity/people.py +0 -0
  246. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/identity/registry.py +0 -0
  247. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/__init__.py +0 -0
  248. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/bundle.py +0 -0
  249. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/check.py +0 -0
  250. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/contracts.py +0 -0
  251. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/experiment.py +0 -0
  252. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/flows.py +0 -0
  253. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/gaps.py +0 -0
  254. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/gate.py +0 -0
  255. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/gather.py +0 -0
  256. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/generator.py +0 -0
  257. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/inventory.py +0 -0
  258. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/okf.py +0 -0
  259. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/pipeline.py +0 -0
  260. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/render.py +0 -0
  261. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/requests.py +0 -0
  262. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/service.py +0 -0
  263. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/staleness.py +0 -0
  264. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/__init__.py +0 -0
  265. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/adrs.py +0 -0
  266. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/contracts.py +0 -0
  267. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/deployments.py +0 -0
  268. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/derive.py +0 -0
  269. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/interfaces.py +0 -0
  270. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/refresh.py +0 -0
  271. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/render.py +0 -0
  272. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/schemas.py +0 -0
  273. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/text.py +0 -0
  274. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/tree.py +0 -0
  275. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/language/__init__.py +0 -0
  276. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/language/assent.py +0 -0
  277. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/listeners.py +0 -0
  278. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/loader.py +0 -0
  279. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/memory/__init__.py +0 -0
  280. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/memory/ledger.py +0 -0
  281. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/memory/messages.py +0 -0
  282. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/memory/recall.py +0 -0
  283. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/memory/store.py +0 -0
  284. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/namespace.py +0 -0
  285. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/observability/__init__.py +0 -0
  286. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/observability/events.py +0 -0
  287. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/observability/job_record.py +0 -0
  288. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/observability/query.py +0 -0
  289. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/observability/registry.py +0 -0
  290. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/observability/sqlite_metrics.py +0 -0
  291. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/observability/trajectory.py +0 -0
  292. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/__init__.py +0 -0
  293. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/concepts.py +0 -0
  294. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/context.py +0 -0
  295. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/cover.py +0 -0
  296. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/firstrun.py +0 -0
  297. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/history.py +0 -0
  298. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/infer.py +0 -0
  299. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/live_ci.py +0 -0
  300. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/onboard.py +0 -0
  301. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/preview_infer.py +0 -0
  302. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/preview_product.py +0 -0
  303. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/preview_propose.py +0 -0
  304. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/propose_manifest.py +0 -0
  305. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/questions.py +0 -0
  306. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/readiness.py +0 -0
  307. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/renew.py +0 -0
  308. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/spend.py +0 -0
  309. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/ops/__init__.py +0 -0
  310. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/ops/impediment.py +0 -0
  311. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/orchestrator/__init__.py +0 -0
  312. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/orchestrator/errors.py +0 -0
  313. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/orchestrator/merge_policy.py +0 -0
  314. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/orchestrator/operator_guidelines.py +0 -0
  315. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/orchestrator/promotion.py +0 -0
  316. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/orchestrator/risk.py +0 -0
  317. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/orchestrator/validation.py +0 -0
  318. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/engineering.md +0 -0
  319. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/floor.yaml +0 -0
  320. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/profiles/prototype.yaml +0 -0
  321. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/profiles/regulated.yaml +0 -0
  322. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/requirements/0000-template.md +0 -0
  323. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/roles/coordinator.md +0 -0
  324. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/roles/executor.md +0 -0
  325. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/roles/planner.md +0 -0
  326. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/roles/product.md +0 -0
  327. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/roles/recovery.md +0 -0
  328. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/roles/sizer.md +0 -0
  329. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/roles/techlead.md +0 -0
  330. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/tdd.md +0 -0
  331. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/own_work.py +0 -0
  332. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/paths.py +0 -0
  333. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/plugins.py +0 -0
  334. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/__init__.py +0 -0
  335. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/authz.py +0 -0
  336. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/census.py +0 -0
  337. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/conformance.py +0 -0
  338. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/context_writes.py +0 -0
  339. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/floor.py +0 -0
  340. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/presets.py +0 -0
  341. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/profiles.py +0 -0
  342. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/protected.py +0 -0
  343. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/test_work.py +0 -0
  344. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preflight.py +0 -0
  345. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/presets/node.yaml +0 -0
  346. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/presets/python.yaml +0 -0
  347. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/presets/security-oss.yaml +0 -0
  348. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/presets/terraform.yaml +0 -0
  349. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/admit.py +0 -0
  350. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/assemble.py +0 -0
  351. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/plan.py +0 -0
  352. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/product.py +0 -0
  353. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/read.py +0 -0
  354. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/reap.py +0 -0
  355. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/unit.py +0 -0
  356. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/__init__.py +0 -0
  357. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/addressing.py +0 -0
  358. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/asked.py +0 -0
  359. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/briefing.py +0 -0
  360. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/brownfield.py +0 -0
  361. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/cap.py +0 -0
  362. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/capabilities.py +0 -0
  363. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/chain.py +0 -0
  364. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/channel.py +0 -0
  365. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/clock.py +0 -0
  366. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/config.py +0 -0
  367. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/conversation.py +0 -0
  368. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/corpus.py +0 -0
  369. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/distil.py +0 -0
  370. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/documents/__init__.py +0 -0
  371. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/documents/ingest.py +0 -0
  372. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/documents/reading.py +0 -0
  373. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/documents/record.py +0 -0
  374. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/documents/store.py +0 -0
  375. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/domain.py +0 -0
  376. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/evaluation/__init__.py +0 -0
  377. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/evaluation/__main__.py +0 -0
  378. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/evaluation/battery.py +0 -0
  379. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/evaluation/run.py +0 -0
  380. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/evaluation/score.py +0 -0
  381. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/facts.py +0 -0
  382. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/followup.py +0 -0
  383. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/index/__init__.py +0 -0
  384. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/index/items.py +0 -0
  385. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/index/retrieval.py +0 -0
  386. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/index/search.py +0 -0
  387. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/index/store.py +0 -0
  388. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/index/sync.py +0 -0
  389. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/intents.py +0 -0
  390. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/key.py +0 -0
  391. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/loader.py +0 -0
  392. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/needs_action.py +0 -0
  393. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/onboard.py +0 -0
  394. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/page.py +0 -0
  395. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/queue.py +0 -0
  396. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/reading.py +0 -0
  397. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/release.py +0 -0
  398. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/requester.py +0 -0
  399. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/semaphore.py +0 -0
  400. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/sessions.py +0 -0
  401. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/sight.py +0 -0
  402. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/sources.py +0 -0
  403. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/speaker.py +0 -0
  404. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/staging.py +0 -0
  405. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/triage.py +0 -0
  406. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/workspace.py +0 -0
  407. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/registry.py +0 -0
  408. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/review/__init__.py +0 -0
  409. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/__init__.py +0 -0
  410. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/card_repo.py +0 -0
  411. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/host.py +0 -0
  412. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/repairable.py +0 -0
  413. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/__init__.py +0 -0
  414. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/connection.py +0 -0
  415. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/poller.py +0 -0
  416. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/schedule.py +0 -0
  417. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/standing.py +0 -0
  418. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/starter.py +0 -0
  419. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/vocabulary.py +0 -0
  420. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/toolbox.py +0 -0
  421. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/scheduler.py +0 -0
  422. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/semver.py +0 -0
  423. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/techlead/__init__.py +0 -0
  424. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/techlead/classify.py +0 -0
  425. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/techlead/diagnosis.py +0 -0
  426. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/techlead/memory.py +0 -0
  427. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/techlead/pack.py +0 -0
  428. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/techlead/watch.py +0 -0
  429. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/testing/__init__.py +0 -0
  430. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/testing/local_flow.py +0 -0
  431. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/util/__init__.py +0 -0
  432. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/util/bounded.py +0 -0
  433. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/util/causes.py +0 -0
  434. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/util/filelock.py +0 -0
  435. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/util/scratch.py +0 -0
  436. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory.egg-info/dependency_links.txt +0 -0
  437. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory.egg-info/entry_points.txt +0 -0
  438. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory.egg-info/requires.txt +0 -0
  439. {openfactory-0.4.0 → openfactory-0.4.2}/openfactory.egg-info/top_level.txt +0 -0
  440. {openfactory-0.4.0 → openfactory-0.4.2}/setup.cfg +0 -0
  441. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_banner_line_does_not_kill_the_review.py +0 -0
  442. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_budget_nothing_spends_is_not_a_defect.py +0 -0
  443. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_card_can_be_previewed.py +0 -0
  444. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_card_is_named_in_the_forge_only_where_the_forge_owns_it.py +0 -0
  445. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_card_s_base_is_the_base_the_job_starts_from.py +0 -0
  446. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_card_says_who_asked_for_it.py +0 -0
  447. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_card_that_was_split_is_not_delivered_until_its_children_are.py +0 -0
  448. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_case_does_not_outlive_its_test.py +0 -0
  449. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_concept_is_earned_not_declared.py +0 -0
  450. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_context_repository_is_creatable_on_azure_too.py +0 -0
  451. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_count_is_a_number_not_a_sentence.py +0 -0
  452. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_credential_is_asked_of_its_own_axis.py +0 -0
  453. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_decision_is_written_down.py +0 -0
  454. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_declared_environment_is_observed_or_named.py +0 -0
  455. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_declined_read_is_said_where_it_is_read.py +0 -0
  456. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_delivered_card_is_closed_by_its_tracker.py +0 -0
  457. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_delivered_ticket_is_not_rerun.py +0 -0
  458. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_deployment_can_run_a_preview.py +0 -0
  459. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_diff_that_could_not_be_read_is_not_an_empty_diff.py +0 -0
  460. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_disabled_project_does_not_look_armed.py +0 -0
  461. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_double_without_intake_answers_every_turn.py +0 -0
  462. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_failed_board_read_is_not_a_wrong_root.py +0 -0
  463. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_failing_check_is_read_for_what_it_is.py +0 -0
  464. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_failing_setup_is_not_silent.py +0 -0
  465. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_file_nothing_describes_is_the_least_safe_to_change.py +0 -0
  466. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_fingerprint_gains_a_reader.py +0 -0
  467. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_finished_card_is_closed_as_delivered.py +0 -0
  468. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_finished_job_is_never_restarted_from_the_base.py +0 -0
  469. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_frame_does_not_erase_what_it_omits.py +0 -0
  470. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_free_deployment_can_read_its_logs.py +0 -0
  471. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_free_deployment_resumes_its_own_sessions.py +0 -0
  472. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_fresh_install_reads_an_empty_store.py +0 -0
  473. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_fresh_install_registers_no_projects.py +0 -0
  474. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_gate_is_not_a_stall.py +0 -0
  475. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_gate_that_could_not_run.py +0 -0
  476. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_gate_that_holds_says_so_where_the_person_decides.py +0 -0
  477. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_green_deploy_asks_somebody_to_look.py +0 -0
  478. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_green_environment_is_green_for_THIS_change.py +0 -0
  479. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_guideline_stays_inside_the_repository.py +0 -0
  480. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_hostile_value_stays_data.py +0 -0
  481. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_human_gate_is_not_a_review.py +0 -0
  482. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_jira_project_is_a_board.py +0 -0
  483. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_job_branches_from_the_base_the_forge_holds.py +0 -0
  484. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_killed_mutation_run_cannot_hide.py +0 -0
  485. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_local_deployment_names_no_vendor.py +0 -0
  486. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_machine_made_hold_says_its_own_cause.py +0 -0
  487. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_manifest_can_be_proven_before_it_is_merged.py +0 -0
  488. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_manifest_outside_the_repository_is_not_proposed.py +0 -0
  489. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_manifest_that_loads_is_not_a_manifest_that_is_right.py +0 -0
  490. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_message_never_claims_an_action_nobody_takes.py +0 -0
  491. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_message_only_teaches_a_verb_the_channel_parses.py +0 -0
  492. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_model_nobody_can_run_is_not_a_setting.py +0 -0
  493. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_name_nobody_registered_is_not_removed.py +0 -0
  494. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_named_check_is_not_dropped.py +0 -0
  495. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_negation_the_bridge_carries_is_refused.py +0 -0
  496. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_pass_in_flight_is_not_a_gate.py +0 -0
  497. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_pass_that_changed_nothing.py +0 -0
  498. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_path_nothing_declares_is_not_the_freest.py +0 -0
  499. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_path_registers_itself.py +0 -0
  500. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_paused_factory_says_so.py +0 -0
  501. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_paused_pass_is_charged.py +0 -0
  502. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_person_has_more_than_one_conversation.py +0 -0
  503. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_person_is_invited_not_signed_up.py +0 -0
  504. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_personal_accounts_board_is_readable.py +0 -0
  505. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_personal_boards_columns_can_be_read.py +0 -0
  506. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_poller_that_is_on_is_not_a_poller_that_ticks.py +0 -0
  507. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_preexisting_context_repo_is_declarable.py +0 -0
  508. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_preview_is_declared_by_the_project_and_decided_by_the_operator.py +0 -0
  509. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_preview_is_ended_by_the_reaper.py +0 -0
  510. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_preview_is_proposed_from_what_the_repository_says.py +0 -0
  511. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_preview_is_reached_on_one_machine.py +0 -0
  512. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_preview_opens_on_one_machine.py +0 -0
  513. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_preview_reaches_nothing_of_the_host.py +0 -0
  514. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_preview_runs_on_a_real_daemon.py +0 -0
  515. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_preview_starts_on_a_real_daemon.py +0 -0
  516. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_probe_set_is_pinned_whole.py +0 -0
  517. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_process_that_approves_keeps_one_engine_client.py +0 -0
  518. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_product_is_its_context_repository.py +0 -0
  519. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_project_can_change_the_language_it_speaks_first.py +0 -0
  520. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_project_declares_what_it_is.py +0 -0
  521. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_project_is_not_registered_as_the_wrong_vendor.py +0 -0
  522. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_project_nobody_registered_is_never_a_500.py +0 -0
  523. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_promotion_the_box_cannot_run_is_refused_before_the_first_card.py +0 -0
  524. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_proof_that_was_not_recorded_says_so.py +0 -0
  525. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_proposal_can_carry_what_to_change.py +0 -0
  526. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_proposal_whose_base_moved_still_lands_on_the_local_forge.py +0 -0
  527. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_proposed_command_can_run_where_the_box_runs_it.py +0 -0
  528. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_provider_is_named_by_its_own_row.py +0 -0
  529. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_pull_request_is_read_and_merged_in_its_own_repository.py +0 -0
  530. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_pull_that_changes_nothing_is_impossible_to_miss.py +0 -0
  531. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_question_reaches_the_person_who_asked.py +0 -0
  532. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_range_is_a_citation.py +0 -0
  533. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_read_that_failed_is_not_an_empty_floor.py +0 -0
  534. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_rebuild_is_not_a_change.py +0 -0
  535. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_ref_that_is_not_a_number.py +0 -0
  536. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_remedy_names_a_document_that_exists.py +0 -0
  537. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_repaired_card_is_announced_on_any_tracker.py +0 -0
  538. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_repository_on_the_former_name_is_refused_at_every_door.py +0 -0
  539. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_retired_pipeline_is_not_a_gate.py +0 -0
  540. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_review_belongs_to_the_code_it_read.py +0 -0
  541. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_scenario_is_one_criterion.py +0 -0
  542. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_scratch_directory_is_the_only_thing_we_delete.py +0 -0
  543. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_skip_is_something_that_happened.py +0 -0
  544. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_staged_decision_survives_a_refresh.py +0 -0
  545. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_staged_proposal_does_not_outlive_its_test.py +0 -0
  546. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_store_that_cannot_be_read_authorizes_nobody_and_says_so.py +0 -0
  547. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_stranger_can_add_a_role.py +0 -0
  548. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_stranger_can_add_an_adapter.py +0 -0
  549. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_suite_that_stopped_collecting_is_not_a_green_suite.py +0 -0
  550. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_ticket_ref_is_never_typed_as_a_number.py +0 -0
  551. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_ticket_written_in_portuguese.py +0 -0
  552. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_trust_file_nobody_reads_is_a_green_proof.py +0 -0
  553. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_typed_instruction_reaches_the_same_row_as_the_button.py +0 -0
  554. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_verb_says_what_to_put_in_it.py +0 -0
  555. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_verdict_nobody_answers_is_said_so_inside_the_deadline.py +0 -0
  556. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_wait_can_say_until_when.py +0 -0
  557. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_wedged_job_has_an_exit.py +0 -0
  558. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_wedged_job_is_seen.py +0 -0
  559. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_withdrawn_card_is_not_delivered_on_jira.py +0 -0
  560. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_withdrawn_card_lands_in_the_sites_own_status_on_jira.py +0 -0
  561. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_write_that_did_not_land_is_not_counted.py +0 -0
  562. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_yes_is_an_answer.py +0 -0
  563. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_accept_flows_end_to_end.py +0 -0
  564. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_acceptance_loop.py +0 -0
  565. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_accepting_starts_the_work.py +0 -0
  566. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_acknowledgement.py +0 -0
  567. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_adapter_conformance_suite.py +0 -0
  568. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_advisory_findings_survive_save.py +0 -0
  569. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_agent_harness.py +0 -0
  570. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_agent_resume_c2.py +0 -0
  571. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_agent_roles.py +0 -0
  572. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_agent_stream.py +0 -0
  573. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_agent_token_pool.py +0 -0
  574. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_already_asked_is_answered_from_the_board_not_the_transcript.py +0 -0
  575. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_activity_uses_the_client_its_worker_holds.py +0 -0
  576. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_advisory_gate_cannot_hold_a_pickup.py +0 -0
  577. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_advisory_gate_reports_and_never_blocks.py +0 -0
  578. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_environment_written_before_this_change_still_resolves_the_old_path.py +0 -0
  579. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_intake_is_a_typed_case.py +0 -0
  580. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_open_question_can_be_retired.py +0 -0
  581. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_open_question_is_an_offer_not_a_toll.py +0 -0
  582. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_unread_collection_is_not_an_empty_one.py +0 -0
  583. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_unread_review_is_not_a_rejection.py +0 -0
  584. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_unreadable_store_is_not_an_empty_one.py +0 -0
  585. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_api.py +0 -0
  586. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_auto_merge_is_judged_from_the_gates_that_were_read.py +0 -0
  587. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_board_is_vendor_neutral.py +0 -0
  588. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_board_read_cost.py +0 -0
  589. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_bot_push.py +0 -0
  590. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_box_carries_the_provider_kind.py +0 -0
  591. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_box_prove.py +0 -0
  592. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_breakdown_reuses_what_exists.py +0 -0
  593. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_brownfield_wired.py +0 -0
  594. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_c18_has_an_azure_expression.py +0 -0
  595. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_c18_reaches_every_entry_point.py +0 -0
  596. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_capabilities_and_checks.py +0 -0
  597. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_card_maintenance_channel.py +0 -0
  598. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_causes.py +0 -0
  599. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_ci_runs_what_we_run.py +0 -0
  600. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_client_board_is_not_a_test_bench.py +0 -0
  601. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_commit_workflow_strip.py +0 -0
  602. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_compose_forwards_the_whole_env_file.py +0 -0
  603. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_confirmation_by_click.py +0 -0
  604. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_confirmation_is_understood.py +0 -0
  605. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_context.py +0 -0
  606. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_conversation_worlds.py +0 -0
  607. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_create_repository_survives_an_app_token.py +0 -0
  608. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_decision.py +0 -0
  609. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_decision_loop.py +0 -0
  610. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_deploy_watch_workflow.py +0 -0
  611. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_diff_hygiene.py +0 -0
  612. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_doctor.py +0 -0
  613. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_doctor_checks_the_product_link.py +0 -0
  614. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_env_apply_answers_in_the_readers_language.py +0 -0
  615. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_env_apply_takes_a_path_like_env_read.py +0 -0
  616. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_env_proposes_before_it_verifies.py +0 -0
  617. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_event_sinks.py +0 -0
  618. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_every_FROM_the_release_builds_resolves_without_the_local_daemon.py +0 -0
  619. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_every_image_the_compose_file_names_is_one_the_release_builds.py +0 -0
  620. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_every_mutation_plan_can_run.py +0 -0
  621. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_factory_asks_for_help.py +0 -0
  622. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_filed_work_is_reachable.py +0 -0
  623. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_first_real_conversation.py +0 -0
  624. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_forge_ci.py +0 -0
  625. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_forge_deploy.py +0 -0
  626. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_forge_idempotency.py +0 -0
  627. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_foundation.py +0 -0
  628. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_gh_is_authenticated.py +0 -0
  629. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_handoff.py +0 -0
  630. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_init_asks_for_one_machine.py +0 -0
  631. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_init_generates_the_deployment.py +0 -0
  632. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_init_speaks_to_the_operator_not_to_us.py +0 -0
  633. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_init_that_acts.py +0 -0
  634. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_internal_imports_resolve.py +0 -0
  635. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_judge_verdict_parsing.py +0 -0
  636. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_kernel_names_no_vendor.py +0 -0
  637. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_knowledge.py +0 -0
  638. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_knowledge_build_reaches_a_factory_cloned_project.py +0 -0
  639. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_knowledge_derived_not_cached.py +0 -0
  640. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_knowledge_experiment.py +0 -0
  641. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_knowledge_pipeline.py +0 -0
  642. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_local_flow.py +0 -0
  643. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_loops_are_reachable.py +0 -0
  644. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_manifest_version.py +0 -0
  645. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_memory_ledger.py +0 -0
  646. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_memory_recall_eval.py +0 -0
  647. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_memory_store.py +0 -0
  648. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_merge_policy.py +0 -0
  649. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_metrics.py +0 -0
  650. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_no_card_id_reaches_a_stranger.py +0 -0
  651. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_no_checkout_assumes_a_branch_name.py +0 -0
  652. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_no_front_end_pays_for_the_engines_client_by_accident.py +0 -0
  653. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_no_gesture_exists_in_one_language_only.py +0 -0
  654. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_no_module_is_ever_called_like_a_function.py +0 -0
  655. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_no_plumbing_reaches_the_client.py +0 -0
  656. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_no_silent_failures.py +0 -0
  657. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_no_vendor_in_the_core.py +0 -0
  658. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_non_numeric_refs_reach_the_api.py +0 -0
  659. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_nothing_speaks_before_it_asks_the_language.py +0 -0
  660. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_observability_registries.py +0 -0
  661. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_office_documents_are_read.py +0 -0
  662. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_onboard_builds_the_context_too.py +0 -0
  663. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_onboard_proposes_a_measured_setup.py +0 -0
  664. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_onboarding_a_context_that_already_exists.py +0 -0
  665. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_onboarding_backfills_the_context.py +0 -0
  666. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_onboarding_creates_the_context_repository.py +0 -0
  667. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_onboarding_firstrun.py +0 -0
  668. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_one_author_writes_the_close_of_a_repair_brief.py +0 -0
  669. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_one_author_writes_the_order_of_a_recovery_and_a_resume.py +0 -0
  670. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_one_cost_for_a_ticket_on_every_surface.py +0 -0
  671. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_one_memory_per_product.py +0 -0
  672. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_one_process_one_installation.py +0 -0
  673. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_one_question_decides_where_the_factory_runs.py +0 -0
  674. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_one_turn_engine.py +0 -0
  675. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_opencode_harness.py +0 -0
  676. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_operator_guidelines.py +0 -0
  677. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_orphaned_cards_are_repointed.py +0 -0
  678. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_panel_approval_store.py +0 -0
  679. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_panel_reads_events_without_aws.py +0 -0
  680. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_park_alert.py +0 -0
  681. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_paths_are_traversal_safe.py +0 -0
  682. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_permission_is_an_order_in_every_language.py +0 -0
  683. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_ports_are_serialisable.py +0 -0
  684. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_preflight.py +0 -0
  685. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_preflight_json_is_the_document_the_agent_lane_reads.py +0 -0
  686. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_preflight_names_a_remedy_for_every_thing_it_refuses.py +0 -0
  687. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_preflight_says_which_machine_it_measured.py +0 -0
  688. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_authoring.py +0 -0
  689. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_board_reads.py +0 -0
  690. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_brownfield.py +0 -0
  691. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_channel.py +0 -0
  692. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_config.py +0 -0
  693. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_corpus.py +0 -0
  694. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_followup.py +0 -0
  695. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_followup_e2e.py +0 -0
  696. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_init_writes_a_file_its_own_check_accepts.py +0 -0
  697. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_intents.py +0 -0
  698. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_loader.py +0 -0
  699. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_module.py +0 -0
  700. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_needs_action.py +0 -0
  701. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_role.py +0 -0
  702. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_sees_the_code.py +0 -0
  703. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_simulation.py +0 -0
  704. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_sweep.py +0 -0
  705. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_triage.py +0 -0
  706. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_view_is_stable.py +0 -0
  707. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_voice.py +0 -0
  708. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_workspace.py +0 -0
  709. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_project_add_exposes_language.py +0 -0
  710. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_project_add_speaks_azure_devops.py +0 -0
  711. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_promotion.py +0 -0
  712. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_provenance_in_the_brief.py +0 -0
  713. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_provider_seams.py +0 -0
  714. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_public_core_names_no_forge.py +0 -0
  715. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_recent_runs_outlives_the_engine.py +0 -0
  716. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_registry_is_runtime_state.py +0 -0
  717. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_repo_cache_credentials.py +0 -0
  718. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_requirement_can_be_dropped.py +0 -0
  719. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_requirement_lifecycle.py +0 -0
  720. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_sandbox_registry.py +0 -0
  721. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_scheduler.py +0 -0
  722. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_schedules_are_reachable.py +0 -0
  723. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_somebody_is_asked_to_look_at_what_shipped.py +0 -0
  724. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_something_finally_asks_the_agent.py +0 -0
  725. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_sqlite_metrics.py +0 -0
  726. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_sso_is_a_row_the_core_ships.py +0 -0
  727. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_sweep_records_only_what_posted.py +0 -0
  728. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_techlead_classify.py +0 -0
  729. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_techlead_memory.py +0 -0
  730. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_techlead_self_heal.py +0 -0
  731. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_techlead_watch.py +0 -0
  732. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_telemetry_reads_from_the_configured_sink.py +0 -0
  733. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_temporal_call_arity.py +0 -0
  734. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_temporal_view.py +0 -0
  735. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_acceptance_map_reaches_a_person.py +0 -0
  736. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_add_on_packages_install.py +0 -0
  737. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_ado_board.py +0 -0
  738. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_ado_coordinates_have_one_home.py +0 -0
  739. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_ado_forge.py +0 -0
  740. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_ado_pipelines.py +0 -0
  741. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_ado_tracker.py +0 -0
  742. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_alert_names_its_ticket_on_any_tracker.py +0 -0
  743. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_announcement_carries_the_verdict.py +0 -0
  744. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_app_key_reaches_every_entry_point.py +0 -0
  745. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_app_permission_table_has_one_home.py +0 -0
  746. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_approver_verbs_ask_which_store_is_in_force.py +0 -0
  747. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_areas_that_change_are_the_ones_that_matter.py +0 -0
  748. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_attended_driver_records_what_it_spent.py +0 -0
  749. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_backfill_is_metered.py +0 -0
  750. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_backfill_names_the_real_reason.py +0 -0
  751. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_backfill_reads_every_source.py +0 -0
  752. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_backfills_questions_can_be_finished.py +0 -0
  753. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_base_branch_is_asked_not_assumed.py +0 -0
  754. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_bench_is_not_the_case.py +0 -0
  755. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_board_keeps_your_place.py +0 -0
  756. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_board_lives_in_one_file.py +0 -0
  757. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_board_names_its_own_pickup_column.py +0 -0
  758. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_board_port_takes_any_providers_ref.py +0 -0
  759. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_board_row_says_which_stage_its_column_is.py +0 -0
  760. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_board_says_where_it_lives.py +0 -0
  761. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_can_obtain_the_repository.py +0 -0
  762. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_can_reach_the_pr_branch.py +0 -0
  763. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_claims_only_what_it_does.py +0 -0
  764. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_clones_from_the_forge_it_was_told.py +0 -0
  765. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_does_not_run_the_clients_shell_profile.py +0 -0
  766. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_env_is_a_named_seam.py +0 -0
  767. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_image_resolves_in_one_place.py +0 -0
  768. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_image_the_worker_spawns_is_one_the_install_pulls.py +0 -0
  769. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_program_can_be_launched.py +0 -0
  770. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_proof_is_watchable.py +0 -0
  771. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_says_where_the_harness_is.py +0 -0
  772. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_says_where_the_operator_guidelines_are.py +0 -0
  773. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_takes_text_the_command_line_never_carries.py +0 -0
  774. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_transmits_while_it_runs.py +0 -0
  775. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_boxed_job_entrypoint.py +0 -0
  776. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_branch_carries_the_products_name.py +0 -0
  777. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_briefing.py +0 -0
  778. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_budget_read_leaves_the_panels_loop.py +0 -0
  779. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_button_without_a_gate.py +0 -0
  780. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_card_carries_ONE_acceptance_section.py +0 -0
  781. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_card_moves_even_when_the_link_cannot_be_built.py +0 -0
  782. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_card_says_what_the_floor_says.py +0 -0
  783. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_chat_has_its_own_fences.py +0 -0
  784. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_chat_is_a_directory_delete.py +0 -0
  785. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_chat_thread_survives_a_refresh.py +0 -0
  786. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_ci_is_read_more_than_once.py +0 -0
  787. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_cli_refuses_in_sentences.py +0 -0
  788. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_cli_runs_in_the_deployments_box.py +0 -0
  789. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_client_never_reads_an_emoji.py +0 -0
  790. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_client_releases_production.py +0 -0
  791. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_cloud_is_a_directory_delete.py +0 -0
  792. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_columns_and_the_identity_are_the_platforms.py +0 -0
  793. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_compose_file_can_be_installed_and_built_from_one_file.py +0 -0
  794. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_compose_row_runs_what_was_admitted.py +0 -0
  795. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_confirmation_executor.py +0 -0
  796. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_context_proposal_is_reachable.py +0 -0
  797. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_context_repository_can_be_created.py +0 -0
  798. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_context_repository_exists_on_this_runtime.py +0 -0
  799. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_conversation_is_pinned.py +0 -0
  800. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_core_addon_ledger.py +0 -0
  801. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_core_boundary.py +0 -0
  802. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_core_does_not_need_a_cloud.py +0 -0
  803. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_core_is_a_core.py +0 -0
  804. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_core_names_no_vendor.py +0 -0
  805. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_credential_scan_reads_a_delimiter.py +0 -0
  806. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_default_language_is_the_products.py +0 -0
  807. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_diff_decides_scope_and_what_validates.py +0 -0
  808. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_distribution_ships_what_it_tells_you_to_copy.py +0 -0
  809. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_docs_do_not_drift.py +0 -0
  810. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_docs_name_no_vendor_as_the_core.py +0 -0
  811. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_docs_say_which_promise.py +0 -0
  812. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_doctor_names_the_gates_only_a_person_settles.py +0 -0
  813. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_doctor_names_the_operator_guidelines.py +0 -0
  814. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_doctor_never_says_no_gate_about_a_branch_it_could_not_read.py +0 -0
  815. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_doctor_says_how_the_product_reads.py +0 -0
  816. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_doctor_says_where_project_less_speech_goes.py +0 -0
  817. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_doctor_survives_its_own_probes.py +0 -0
  818. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_doctor_tells_the_truth_about_this_machine.py +0 -0
  819. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_documentation_has_one_front_door.py +0 -0
  820. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_documented_default_is_the_real_one.py +0 -0
  821. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_documents_are_read.py +0 -0
  822. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_documents_are_read_on_the_schedule_and_on_an_event.py +0 -0
  823. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_documents_describe_the_product_this_tree_is.py +0 -0
  824. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_documents_name_the_repository_and_keep_their_accents.py +0 -0
  825. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_doors_derive_from_the_registries.py +0 -0
  826. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_end_to_end_install_is_a_script_the_suite_can_run.py +0 -0
  827. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_engine_answers_or_says_so.py +0 -0
  828. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_engine_dying_under_a_job_is_not_a_mystery.py +0 -0
  829. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_engine_starts_only_beside_the_library_its_worker_runs_on.py +0 -0
  830. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_environment_carries_the_products_name.py +0 -0
  831. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_environment_round_is_a_terminal_verb.py +0 -0
  832. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_evaluation_battery.py +0 -0
  833. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_event_axis_is_reached.py +0 -0
  834. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_examples_a_reader_copies_load_on_the_core.py +0 -0
  835. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_extensibility_doc_names_the_real_group.py +0 -0
  836. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_extra_ca_file_is_always_a_valid_pem.py +0 -0
  837. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_factory_asks_before_it_starts.py +0 -0
  838. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_factory_authors_what_it_does_not_know_before_it_changes_it.py +0 -0
  839. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_factory_runs_on_one_machine.py +0 -0
  840. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_factory_runs_without_a_cloud.py +0 -0
  841. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_facts_are_files_the_techlead_can_open.py +0 -0
  842. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_facts_stay_files_for_every_harness.py +0 -0
  843. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_first_hour_fails_by_name.py +0 -0
  844. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_first_round_is_reachable.py +0 -0
  845. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_first_yes_writes_and_the_second_yes_is_on_the_ticket.py +0 -0
  846. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_floor_and_the_inbox_agree.py +0 -0
  847. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_floor_is_a_deployment_default_not_a_transcription.py +0 -0
  848. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_floor_is_a_platform_capability.py +0 -0
  849. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_floor_is_enforced_where_the_money_is.py +0 -0
  850. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_floor_is_not_re_read_on_every_frame.py +0 -0
  851. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_forge_can_read_a_foreign_repository.py +0 -0
  852. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_forge_names_a_card_only_in_its_own_words.py +0 -0
  853. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_forge_opens_a_pr_in_another_repository.py +0 -0
  854. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_form_asks_what_the_address_needs.py +0 -0
  855. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_gate_checks_the_shell_script_a_stranger_runs_first.py +0 -0
  856. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_gate_holds_when_the_store_cannot_be_read.py +0 -0
  857. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_gate_shows_what_the_review_found.py +0 -0
  858. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_generated_environment_names_a_work_directory_that_needs_no_root.py +0 -0
  859. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_harness_endpoint_is_the_clients.py +0 -0
  860. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_harness_is_watched_while_it_runs.py +0 -0
  861. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_harness_pulse.py +0 -0
  862. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_history_says_where_the_work_is.py +0 -0
  863. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_hybrid_index.py +0 -0
  864. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_install_line_the_readme_prints_is_the_url_the_release_publishes_to.py +0 -0
  865. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_installer_knows_exactly_two_facts_the_package_does_not.py +0 -0
  866. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_installer_never_calls_sudo.py +0 -0
  867. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_installer_pins_a_version_and_never_installs_a_floating_tag.py +0 -0
  868. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_intake_memo_is_read_once_and_handed_out_as_a_copy.py +0 -0
  869. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_inventory_counts_what_it_could_not_place.py +0 -0
  870. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_journal_is_where_the_deployment_says.py +0 -0
  871. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_journal_records_how_a_job_ENDED.py +0 -0
  872. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_judging_roles_can_reach_their_model.py +0 -0
  873. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_language_reaches_every_unprompted_surface.py +0 -0
  874. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_lifecycle_names_no_provider.py +0 -0
  875. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_loop_tells_the_truth.py +0 -0
  876. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_manifest_can_be_proposed_server_side.py +0 -0
  877. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_manifest_reference_is_complete.py +0 -0
  878. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_map_does_not_wait_for_a_merge.py +0 -0
  879. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_map_is_published_beside_the_concepts.py +0 -0
  880. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_map_says_what_it_does_not_cover.py +0 -0
  881. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_memory_writes.py +0 -0
  882. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_merge_re_authors_what_it_invalidated.py +0 -0
  883. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_model_is_a_per_project_choice.py +0 -0
  884. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_model_is_set_from_the_cli.py +0 -0
  885. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_mutation_runner_is_not_decoration.py +0 -0
  886. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_namespace_is_the_products_name.py +0 -0
  887. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_net_that_protects_the_client.py +0 -0
  888. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_number_told_is_the_number_written.py +0 -0
  889. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_open_distribution_has_a_voice.py +0 -0
  890. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_operator_hears_the_projects_language.py +0 -0
  891. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_operator_path_names_what_the_code_mints.py +0 -0
  892. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_holds_one_engine_client.py +0 -0
  893. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_is_a_channel.py +0 -0
  894. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_is_pushed_to.py +0 -0
  895. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_names_no_vendor.py +0 -0
  896. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_reads_as_a_control_room.py +0 -0
  897. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_says_a_pass_is_running.py +0 -0
  898. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_says_where_to_change_things.py +0 -0
  899. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_says_whether_work_is_picked_up.py +0 -0
  900. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_says_which_harness.py +0 -0
  901. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_serves_without_the_engines_client.py +0 -0
  902. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_speaks_one_language.py +0 -0
  903. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_touches_no_cloud_locally.py +0 -0
  904. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_platform_reads_a_repository_and_proposes.py +0 -0
  905. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_poller_has_a_lever.py +0 -0
  906. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_preview_axis.py +0 -0
  907. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_carries_no_ones_past.py +0 -0
  908. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_carries_no_owners_name.py +0 -0
  909. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_conversation_is_core.py +0 -0
  910. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_owner_orders_the_backlog_from_chat.py +0 -0
  911. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_owner_reads_an_intake_and_teaches.py +0 -0
  912. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_owner_s_page.py +0 -0
  913. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_owner_writes_the_backlog_order.py +0 -0
  914. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_owners_facts_are_files.py +0 -0
  915. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_path_is_not_github_by_construction.py +0 -0
  916. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_role_is_called_nina.py +0 -0
  917. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_role_speaks_the_clients_language.py +0 -0
  918. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_project_remembers_what_everyone_said.py +0 -0
  919. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_promotion_tail_speaks.py +0 -0
  920. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_proof_gates_each_repository.py +0 -0
  921. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_proof_gates_pickup.py +0 -0
  922. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_proof_on_the_host.py +0 -0
  923. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_proposal_covers_the_floor.py +0 -0
  924. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_public_cut_is_written_down.py +0 -0
  925. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_public_documents_serve_a_stranger.py +0 -0
  926. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_pull_request_lives_in_the_file.py +0 -0
  927. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_pull_request_says_what_the_card_says.py +0 -0
  928. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_pull_request_says_what_the_last_attempt_did.py +0 -0
  929. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_queue_proposes_in_batches.py +0 -0
  930. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_read_model.py +0 -0
  931. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_reading_is_bound_against_the_bundle_that_exists.py +0 -0
  932. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_refusal_reads_the_file_it_would_write.py +0 -0
  933. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_release_assembles_what_the_installer_downloads.py +0 -0
  934. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_remedy_a_refusal_hands_you_can_be_followed.py +0 -0
  935. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_renewal_keeps_the_inventory_current.py +0 -0
  936. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_repair_brief_states_the_failure_it_was_given.py +0 -0
  937. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_repository_moves_to_the_ticket.py +0 -0
  938. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_retrieval_step.py +0 -0
  939. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_review_findings_stay_fixed.py +0 -0
  940. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_review_is_charged_on_every_surface.py +0 -0
  941. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_reviewer_can_actually_run.py +0 -0
  942. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_role_does_not_claim_blindness.py +0 -0
  943. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_role_knows_what_day_it_is.py +0 -0
  944. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_roles_can_reach_the_bundle.py +0 -0
  945. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_roles_run_on_the_local_rows.py +0 -0
  946. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_second_deployment_is_not_the_first.py +0 -0
  947. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_second_yes_is_the_requesters.py +0 -0
  948. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_security_policy_promises_what_the_scrub_does.py +0 -0
  949. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_semaphore_on_work.py +0 -0
  950. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_set_ends_together.py +0 -0
  951. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_shape_is_read_and_admitted.py +0 -0
  952. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_shell_we_ship_runs_on_both_seds.py +0 -0
  953. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_sizer_names_the_area_it_expects_to_touch.py +0 -0
  954. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_socket_is_real_and_scoped.py +0 -0
  955. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_speaker_and_the_reply.py +0 -0
  956. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_split_says_which_card_to_drag.py +0 -0
  957. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_starter_template_passes_its_own_floor.py +0 -0
  958. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_station_strip_resets_on_a_re_run.py +0 -0
  959. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_stock_box_runs_what_the_proposer_proposes.py +0 -0
  960. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_structural_documents_speak_the_projects_portuguese.py +0 -0
  961. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_suite_cannot_reach_a_live_engine.py +0 -0
  962. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_suite_cannot_reach_production.py +0 -0
  963. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_suite_never_writes_the_registry_your_shell_names.py +0 -0
  964. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_system_layer.py +0 -0
  965. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_system_layer_is_published.py +0 -0
  966. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_techlead_answers_without_a_channel.py +0 -0
  967. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_techlead_asks_the_engine_on_a_loop_that_outlives_the_question.py +0 -0
  968. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_techlead_can_see_the_change_it_judges.py +0 -0
  969. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_techlead_does_not_cry_wolf.py +0 -0
  970. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_techlead_reads_through_the_ports.py +0 -0
  971. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_techlead_remembers_the_conversation.py +0 -0
  972. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_techlead_sees_a_jira_floor.py +0 -0
  973. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_ticket_url_is_the_trackers_own.py +0 -0
  974. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_toolbox.py +0 -0
  975. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_tracker_has_a_read_side.py +0 -0
  976. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_tracker_reads_what_a_person_wrote.py +0 -0
  977. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_trajectory_is_a_measurement.py +0 -0
  978. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_trajectory_reaches_the_record.py +0 -0
  979. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_two_halves_agree_on_which_code_they_run.py +0 -0
  980. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_vendors_credential_is_found_by_default.py +0 -0
  981. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_verifier_is_not_editable_by_what_it_verifies.py +0 -0
  982. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_walk_respects_what_the_repository_ignores.py +0 -0
  983. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_web_conversation_is_directed_at_the_person_in_it.py +0 -0
  984. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_wheel_is_published_under_the_name_the_docs_tell_you_to_install.py +0 -0
  985. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_wheel_ships_what_the_platform_needs.py +0 -0
  986. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_word_list_is_a_shortcut_not_a_gate.py +0 -0
  987. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_worker_waits_for_the_engine_to_listen.py +0 -0
  988. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_three_commands_one_verdict.py +0 -0
  989. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_token_provider.py +0 -0
  990. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_tracker_board_writes.py +0 -0
  991. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_tracker_is_vendor_neutral.py +0 -0
  992. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_transcript_memory.py +0 -0
  993. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_two_projects_do_not_share_a_box.py +0 -0
  994. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_voice_vocabulary.py +0 -0
  995. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_walking_skeleton.py +0 -0
  996. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_what_git_refuses_the_person_reads.py +0 -0
  997. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_what_the_card_shows_inside_a_bullet_is_what_is_read.py +0 -0
  998. {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_who_is_asking.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openfactory
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: A framework to run software tickets autonomously with coding agents — policies authorize actions, humans evaluate results.
5
5
  Author: The OpenFactory Authors
6
6
  License-Expression: Apache-2.0
@@ -210,7 +210,7 @@ form:
210
210
  | [docs/reference/cli.md](docs/reference/cli.md) | every command (the `env`/`box`/`product` surfaces are walked in ONBOARDING) |
211
211
  | [docs/reference/product-role.md](docs/reference/product-role.md) | switching on the product owner |
212
212
  | [docs/writing-an-addon.md](docs/writing-an-addon.md) | your deployment needs a provider the core does not ship — a row, end to end, editing nothing here |
213
- | [docs/adr/](docs/adr/) | why it is built this way (53 decision records) |
213
+ | [docs/adr/](docs/adr/) | why it is built this way (54 decision records) |
214
214
 
215
215
  ## Status
216
216
 
@@ -4,4 +4,4 @@ Policies authorize actions; humans evaluate results. See
4
4
  docs/adr/0001-foundational-conceptual-model.md for the conceptual model.
5
5
  """
6
6
 
7
- __version__ = "0.4.0"
7
+ __version__ = "0.4.2"
@@ -2058,7 +2058,7 @@ _ANSWERS = ("approve", "reject")
2058
2058
 
2059
2059
 
2060
2060
  async def _product_answer(*, project: str, token: str, answer: str, by: Actor,
2061
- yes: object = False) -> Outcome:
2061
+ yes: object = False, message_id: str = "") -> Outcome:
2062
2062
  """Answer a proposal the product role STAGED — the pair of `product_pending`.
2063
2063
 
2064
2064
  `product_pending` lists what is waiting and hands back a token per row; this is what a person
@@ -2112,6 +2112,13 @@ async def _product_answer(*, project: str, token: str, answer: str, by: Actor,
2112
2112
  f"a staged proposal is answered with {' or '.join(_ANSWERS)}, not {answer!r} — a "
2113
2113
  f"question with two buttons cannot be answered with a third thing. Nothing was "
2114
2114
  f"recorded.", project=proj.name)
2115
+ # THE CLICK'S OWN ID, the page's (#402): the answer is recorded as the reply to it, so the
2116
+ # page that drew the answer finds it in the transcript by identity and draws it once. Held to
2117
+ # the shape `product_say` holds a message id to — it travels into a record and a workflow.
2118
+ minted = str(message_id or "").strip()
2119
+ if minted and not _MESSAGE_ID.match(minted):
2120
+ return refused(INVALID, "a message id is 8 to 128 letters, digits, '-' or '_'.",
2121
+ project=proj.name)
2115
2122
 
2116
2123
  client, bad_engine = await _connected()
2117
2124
  if bad_engine:
@@ -2123,7 +2130,8 @@ async def _product_answer(*, project: str, token: str, answer: str, by: Actor,
2123
2130
  raw = await client.execute_workflow(
2124
2131
  "ProductAnswerWorkflow",
2125
2132
  ProductAnswerInput(project=proj.name, token=tok, approved=(said == "approve"),
2126
- actor=by.id, via=getattr(by, "via", "") or ""),
2133
+ actor=by.id, via=getattr(by, "via", "") or "",
2134
+ message_id=minted),
2127
2135
  # KEYED BY THE TOKEN, which already carries the conversation AND the fingerprint of
2128
2136
  # exactly what was staged. Two people answering the same proposal collide on purpose —
2129
2137
  # the second gets the first one's result rather than performing it twice — while a
@@ -2697,9 +2705,18 @@ async def _product_agenda(*, project: str, by: Actor) -> Outcome:
2697
2705
  viewer = agenda.Viewer(own=getattr(by, "conversation", "") or "", person=by.id,
2698
2706
  may_read_room=by.may_enter(PRODUCT))
2699
2707
  rows = await asyncio.to_thread(loop_store.read, proj.name)
2700
- found = agenda.items(rows, viewer, room=events.room_of(proj))
2701
- return done(agenda.render(found), project=proj.name, measured_on=_measured_on(by),
2702
- items=[item.as_dict() for item in found])
2708
+ # IN THE PROJECT'S LANGUAGE, AND SAYING WHAT IT IS (#401): a pt-BR product's person read
2709
+ # "tell you when the problem reported is fixed · owed · you" under a tab nothing explained.
2710
+ # `about` and `empty` are the panel's to draw; its own English is only the fallback.
2711
+ from openfactory.product.voice import agenda_about, agenda_empty
2712
+
2713
+ language = getattr(proj, "language", None)
2714
+ found = agenda.items(rows, viewer, room=events.room_of(proj), language=language)
2715
+ agent = getattr(getattr(proj, "product", None), "agent_name", "") or ""
2716
+ return done(agenda.render(found, language=language), project=proj.name,
2717
+ measured_on=_measured_on(by), items=[item.as_dict() for item in found],
2718
+ about=agenda_about(agent_name=agent, language=language),
2719
+ empty=agenda_empty(language))
2703
2720
 
2704
2721
 
2705
2722
  async def _product_cases(*, project: str, by: Actor, thread: str = "") -> Outcome:
@@ -3619,6 +3636,117 @@ async def _product_correct_card(*, project: str, number: str, by: Actor, text: s
3619
3636
  return _write_outcome(result, did=f"corrected #{ref}", project=proj.name)
3620
3637
 
3621
3638
 
3639
+ async def _product_board(*, project: str, by: Actor, card: str = "") -> Outcome:
3640
+ """The cards on the board, and one card's own view — for the product surface (#384).
3641
+
3642
+ THE PRODUCT VIEW HAD NO CARD TO ACT ON. Its Board tab asked the role to triage and nothing more,
3643
+ and `GET /api/board/{project}` is a floor read a product credential is refused — so a person
3644
+ who asked for a card and wanted it gone could not even open it where they work. This is the
3645
+ read that page needs: the open cards with their column, and, for the card they opened, its text
3646
+ and what its controls do (`card_view`). It writes nothing; the controls are
3647
+ `product_withdraw_card`.
3648
+
3649
+ THE THREE ANSWERS TRAVEL, as on the floor's board: `cards` is `None` when the board could not be
3650
+ read and `[]` when it was read and is empty."""
3651
+ import asyncio
3652
+
3653
+ _module, proj, bad = _product_module(project, by=by)
3654
+ if bad:
3655
+ return bad
3656
+ _proj, tracker, board, bad = _board_pair(project)
3657
+ if bad:
3658
+ return bad
3659
+
3660
+ def _read() -> dict:
3661
+ from openfactory.adapters.board.base import stage_key
3662
+ from openfactory.adapters.board.columns import has_started
3663
+ from openfactory.product.authoring import filed_by_the_product_role
3664
+
3665
+ placed = board.columns() if board is not None else {}
3666
+ summaries = tracker.list_tickets(state="open")
3667
+ cards = None
3668
+ if placed is not None and summaries is not None:
3669
+ cards = [{"ref": s.ref, "title": s.title, "column": placed.get(s.ref, ""),
3670
+ "started": has_started(stage_key(board, placed.get(s.ref, "")))
3671
+ if board is not None and placed.get(s.ref) else False,
3672
+ "opened_by_product": filed_by_the_product_role(s.body or "")}
3673
+ for s in summaries]
3674
+ detail = None
3675
+ if (wanted := (card or "").strip()):
3676
+ try:
3677
+ ticket = tracker.get_ticket(wanted)
3678
+ except Exception: # noqa: BLE001 — a card that cannot be read is an answer
3679
+ log.info("the product view could not read card %r", wanted, exc_info=True)
3680
+ detail = {"ref": wanted, "readable": False}
3681
+ else:
3682
+ raw = getattr(ticket, "raw", "") or ""
3683
+ opened = filed_by_the_product_role(raw)
3684
+ state = getattr(ticket, "state", "") or "open"
3685
+ from openfactory.contracts.refs import canonical_ref
3686
+
3687
+ column = (placed or {}).get(canonical_ref(wanted)) if placed is not None else None
3688
+ detail = {"ref": canonical_ref(wanted), "readable": True, "title": ticket.title,
3689
+ "body": raw, "state": state, "column": column or "",
3690
+ "opened_by_product": opened,
3691
+ **card_view(proj, tracker, board, wanted, opened_by=opened,
3692
+ column=column, state=state)}
3693
+ return {"cards": cards, "card": detail}
3694
+
3695
+ read = await asyncio.to_thread(_read)
3696
+ count = "could not be read" if read["cards"] is None else f"{len(read['cards'])} open"
3697
+ return done(f"{proj.name}'s board — {count}", project=proj.name, **read)
3698
+
3699
+
3700
+ async def _product_withdraw_card(*, project: str, number: str, reason: str, by: Actor,
3701
+ remove: object = False) -> Outcome:
3702
+ """Close a card, or remove one nobody has started, from the card on the product view (#384).
3703
+
3704
+ THE CONTROL ON THE CARD, NOT A CONVERSATION. `product_close_card` is the conversation's hand —
3705
+ staged, confirmed with `yes`, naming a survivor — and it asks no stage gate, because the chat
3706
+ that stages it reads nothing first. This row is the card's own control: the confirmation is
3707
+ the one the person just gave on the card, and the gate is the board's, the same one the floor's
3708
+ `card_close` and `card_remove` ask (`_withdraw_refusal`), so the two surfaces refuse the same
3709
+ card for the same sentence. It goes through the product role for every card, whoever opened
3710
+ it: this is the product surface, and the role is who writes on it.
3711
+
3712
+ WHO MAY is the module's answer (`withdraw_card`): a product admin, the person who asked for
3713
+ the card, or an operator (an admin who may enter the floor), whom this row vouches for as the
3714
+ floor's rows do. So the row does not demand `needs_admin` — the requester of a card is on no
3715
+ allowlist, and dropping what you asked for yourself needs nobody's yes."""
3716
+ import asyncio
3717
+
3718
+ _module, proj, bad = _product_module(project, by=by)
3719
+ if bad:
3720
+ return bad
3721
+ _proj, tracker, board, bad = _board_pair(project)
3722
+ if bad:
3723
+ return bad
3724
+ ref = str(number or "").strip().lstrip("#")
3725
+ if not ref:
3726
+ return refused(INVALID, "say which card.")
3727
+ said = (reason or "").strip()
3728
+ if not said:
3729
+ return refused(INVALID, "say why — the reason is what the next reader of the card has, "
3730
+ "and one made only of spaces says nothing.")
3731
+ removing = _said_yes(remove)
3732
+ _kind, unreadable = await asyncio.to_thread(_opened_by, tracker, ref)
3733
+ if unreadable:
3734
+ return refused(CONFLICT, unreadable)
3735
+ stage, refusal = await _withdraw_refusal(proj, board, ref, remove=removing)
3736
+ if refusal:
3737
+ return refused(CONFLICT, refusal)
3738
+ from openfactory.adapters.board.columns import has_finished
3739
+
3740
+ # AN OPERATOR MAY DROP A CARD FROM HERE TOO (#384, decided on the issue: no bureaucracy in
3741
+ # the first cut). The floor's rows already vouch for one; on this surface an operator is the
3742
+ # actor the transport says is an admin AND who may enter the floor — a product-scoped
3743
+ # credential never is, so a business analyst gains nothing by it.
3744
+ operator = bool(by.admin) and by.may_enter(FLOOR)
3745
+ return await _by_the_product_role(proj, ref, by=by, reason=said, remove=removing,
3746
+ delivered=has_finished(stage.key) and not removing,
3747
+ vouched=operator)
3748
+
3749
+
3622
3750
  async def _product_record_decision(*, project: str, number: str, decision: str, by: Actor,
3623
3751
  yes: object = False) -> Outcome:
3624
3752
  """Write a decision taken AFTER the acceptance into the requirement's own register.
@@ -3963,6 +4091,19 @@ def _stage_refusal(proj, board, issue: str, *, act: str = "edit",
3963
4091
  if at.cannot_tell:
3964
4092
  return at.cannot_tell
3965
4093
  key, column = at.key, at.column
4094
+ if act == "remove":
4095
+ # ONLY BEFORE PICKUP, AND NARROWER THAN A CLOSE (#384). Removing is for the cheapest moment
4096
+ # to drop work — nothing spent, nobody reading the card — and a card the factory has taken
4097
+ # up is past it whether or not a job is still on it: what was spent and what was said on
4098
+ # it is history a close keeps and a removal would erase. So `has_started`, not
4099
+ # `may_be_running`, and the engine is never asked. Where a job may be on the card the
4100
+ # close's own sentence stands — ONE copy of it, below; after the job, the sentence says
4101
+ # what is left: close it.
4102
+ if has_started(key) and not may_be_running(key):
4103
+ return (f"{issue} is in {column!r} — the factory has already taken it up, so it can "
4104
+ f"no longer be removed: what was done and said on it is history. Close it "
4105
+ f"instead, and the reason stays on the card.")
4106
+ act = "close"
3966
4107
  if act == "close":
3967
4108
  if may_be_running(key):
3968
4109
  return (f"{issue} is in {column!r} — the factory has taken it up, and a job may be "
@@ -4088,6 +4229,26 @@ _OPENED_FROM = {
4088
4229
  }
4089
4230
 
4090
4231
 
4232
+ def _opened_by(tracker, issue: str) -> tuple[str, str]:
4233
+ """`(which of the product role's writers opened this card, "")` — `""` for a card written on
4234
+ the board — or `("", why nobody can tell)` when the card could not be read (#150, #384).
4235
+
4236
+ ONE READ, TWO QUESTIONS. The edit asks it to refuse (`_product_owned_refusal`); the close and
4237
+ the removal ask it to know WHOSE path the act goes through — the board's own, or the product
4238
+ role's (`_by_the_product_role`). An unreadable card answers neither, and both refuse on it."""
4239
+ from openfactory.product.authoring import filed_by_the_product_role
4240
+
4241
+ try:
4242
+ ticket = tracker.get_ticket(issue)
4243
+ except Exception as exc: # noqa: BLE001 — an unreadable card is an answer, and it refuses
4244
+ log.warning("OPENFACTORY_CARD_OWNER_UNREAD card=%s: could not read the card to tell who "
4245
+ "opened it, so the board's act is refused — %s", issue, exc)
4246
+ return "", (f"{issue} could not be read, so there is no way to tell whether the product "
4247
+ f"role opened it — and a card it opened only the product owner may change. "
4248
+ f"Nothing was changed; try again.")
4249
+ return filed_by_the_product_role(getattr(ticket, "raw", "") or ""), ""
4250
+
4251
+
4091
4252
  def _product_owned_refusal(tracker, issue: str, *, act: str) -> str:
4092
4253
  """Why this card may not be `act`-ed from the board, or `""` when it may (#150).
4093
4254
 
@@ -4100,18 +4261,15 @@ def _product_owned_refusal(tracker, issue: str, *, act: str) -> str:
4100
4261
 
4101
4262
  A CARD THAT CANNOT BE READ REFUSES. Whether the product role opened it is the question, and
4102
4263
  letting the act through on a card that may be somebody's promise is the direction this must not
4103
- fail in — the same choice `_stage_refusal` makes about a board it cannot read."""
4104
- from openfactory.product.authoring import filed_by_the_product_role
4105
-
4106
- try:
4107
- ticket = tracker.get_ticket(issue)
4108
- except Exception as exc: # noqa: BLE001 — an unreadable card is an answer, and it refuses
4109
- log.warning("OPENFACTORY_CARD_OWNER_UNREAD card=%s: could not read the card to tell who "
4110
- "opened it, so the board's %s is refused — %s", issue, act, exc)
4111
- return (f"{issue} could not be read, so there is no way to tell whether the product role "
4112
- f"opened it — and a card it opened only the product owner may change. Nothing was "
4113
- f"changed; try again.")
4114
- kind = filed_by_the_product_role(getattr(ticket, "raw", "") or "")
4264
+ fail in — the same choice `_stage_refusal` makes about a board it cannot read.
4265
+
4266
+ NOW ASKED OF AN EDIT AND A REOPEN ONLY (#384). A close or a removal of such a card is no longer
4267
+ refused: it goes through the product role's own path (`_by_the_product_role`), because
4268
+ dropping a card creates none of the drift this rule exists for — no job reads it, and the role
4269
+ records the drop itself. Changing what the card SAYS still does, and stays refused here."""
4270
+ kind, unreadable = _opened_by(tracker, issue)
4271
+ if unreadable:
4272
+ return unreadable
4115
4273
  if not kind:
4116
4274
  return ""
4117
4275
  source, then = _OPENED_FROM[kind]
@@ -4225,27 +4383,22 @@ async def _card_edit(*, project: str, issue: str, by: Actor, title: str = "",
4225
4383
  project=proj.name, issue=str(issue), changed=",".join(changed), **gate)
4226
4384
 
4227
4385
 
4228
- async def _card_close(*, project: str, issue: str, by: Actor, reason: str = "") -> Outcome:
4229
- """Take a card off the board, with a reason — the operator's own 'this should not be here'."""
4386
+ async def _withdraw_refusal(proj, board, issue: str, *, remove: bool) -> tuple[_Stage, str]:
4387
+ """`(where the card is, why it may not be closed — or removed — now)`, `""` when it may.
4388
+
4389
+ THE ONE GATE BOTH SURFACES' CONTROLS ASK (#384), taken out of `_card_close` whole, so the
4390
+ product view's "Close card" is refused where the board's is and for the same sentence — a
4391
+ second copy is where one surface would come to close a card from under a running job.
4392
+
4393
+ A CLOSE reads the board once (for the refusal AND for the word it records, #162) and asks the
4394
+ engine only where the column says a job may be on the card (review of #191). A REMOVAL asks
4395
+ only the board: it is refused on every card the factory has taken up, job or no job
4396
+ (`_stage_refusal`), so the engine has nothing to add."""
4230
4397
  import asyncio
4231
4398
 
4232
- proj, tracker, board, bad = _board_pair(project)
4233
- if bad:
4234
- return bad
4235
- # A REASON OF ONLY SPACES IS NO REASON. `required` makes `perform` refuse a reason that is
4236
- # missing or exactly `""` — equality, not emptiness — so `" "` reached this row and closed the
4237
- # card with a note ending in a space. This check was once removed as dead, on a surviving
4238
- # mutation row; the row survived because nothing drove a whitespace-only reason (review of
4239
- # #153), which is a weak guard, not dead code.
4240
- said = (reason or "").strip()
4241
- if not said:
4242
- return refused(INVALID, "say why the card is being closed — the reason is what the next "
4243
- "reader of the card has, and one made only of spaces says nothing.")
4244
- refusal = await asyncio.to_thread(_product_owned_refusal, tracker, issue, act="closes")
4245
- if refusal:
4246
- return refused(CONFLICT, refusal)
4247
- # ONE READ OF THE BOARD, for the refusal AND for the word the close records (#162).
4248
4399
  stage = await asyncio.to_thread(_stage, proj, board, issue)
4400
+ if remove:
4401
+ return stage, _stage_refusal(proj, board, issue, act="remove", stage=stage)
4249
4402
  refusal = _stage_refusal(proj, board, issue, act="close", stage=stage)
4250
4403
  if refusal and not stage.cannot_tell:
4251
4404
  # THE COLUMN SAYS A JOB *MAY* BE ON IT; THE ENGINE SAYS WHETHER ONE IS (review of #191).
@@ -4266,6 +4419,59 @@ async def _card_close(*, project: str, issue: str, by: Actor, reason: str = "")
4266
4419
  f"the card closes once no job is on it.")
4267
4420
  # else: a job is running and waiting on nobody, which is exactly what `_stage_refusal`
4268
4421
  # describes and the one shape `stop` accepts. Its sentence stands.
4422
+ return stage, refusal
4423
+
4424
+
4425
+ async def _by_the_product_role(proj, issue: str, *, by: Actor, reason: str, remove: bool,
4426
+ delivered: bool, vouched: bool) -> Outcome:
4427
+ """Close or remove a card THROUGH THE PRODUCT ROLE — the path a card it opened takes from
4428
+ either surface's control, and the product view's for every card (#384).
4429
+
4430
+ THE BOARD ASKS THE ROLE, THE ROLE WRITES. `withdraw_card` is `close_card`'s own close (and the
4431
+ tracker's own removal), so the requirement and the card stay saying the same thing and the
4432
+ conversation the card was asked in is told. The gate that says whether the card may be touched
4433
+ YET is the caller's, asked before this (`_withdraw_refusal`). `vouched` is True only from a
4434
+ floor row, which the action layer let only a floor admin reach."""
4435
+ import asyncio
4436
+
4437
+ from openfactory.contracts.refs import canonical_ref
4438
+
4439
+ module, _proj, bad = _product_module(proj.name, by=by)
4440
+ if bad:
4441
+ return bad
4442
+ result = await asyncio.to_thread(
4443
+ lambda: module.withdraw_card(canonical_ref(issue), actor=by.id, reason=reason,
4444
+ remove=remove, delivered=delivered, vouched=vouched))
4445
+ return _write_outcome(result, did=f"{'removed' if remove else 'closed'} {issue}",
4446
+ project=proj.name, issue=str(issue), removed=bool(remove),
4447
+ delivered=bool(delivered), through="product")
4448
+
4449
+
4450
+ async def _card_close(*, project: str, issue: str, by: Actor, reason: str = "") -> Outcome:
4451
+ """Take a card off the board, with a reason — the operator's own 'this should not be here'."""
4452
+ import asyncio
4453
+
4454
+ proj, tracker, board, bad = _board_pair(project)
4455
+ if bad:
4456
+ return bad
4457
+ # A REASON OF ONLY SPACES IS NO REASON. `required` makes `perform` refuse a reason that is
4458
+ # missing or exactly `""` — equality, not emptiness — so `" "` reached this row and closed the
4459
+ # card with a note ending in a space. This check was once removed as dead, on a surviving
4460
+ # mutation row; the row survived because nothing drove a whitespace-only reason (review of
4461
+ # #153), which is a weak guard, not dead code.
4462
+ said = (reason or "").strip()
4463
+ if not said:
4464
+ return refused(INVALID, "say why the card is being closed — the reason is what the next "
4465
+ "reader of the card has, and one made only of spaces says nothing.")
4466
+ # WHOSE CARD FIRST — BUT NO LONGER TO REFUSE IT (#384). A card the product role opened was
4467
+ # refused here ("only the product owner closes it … ask for it in the conversation"), and the
4468
+ # person who wanted it gone had no button that worked anywhere. It now goes through the role's
4469
+ # own path below; a card nobody can read still refuses, for #150's reason.
4470
+ kind, unreadable = await asyncio.to_thread(_opened_by, tracker, issue)
4471
+ if unreadable:
4472
+ return refused(CONFLICT, unreadable)
4473
+ # ONE READ OF THE BOARD, for the refusal AND for the word the close records (#162).
4474
+ stage, refusal = await _withdraw_refusal(proj, board, issue, remove=False)
4269
4475
  if refusal:
4270
4476
  return refused(CONFLICT, refusal)
4271
4477
 
@@ -4279,6 +4485,9 @@ async def _card_close(*, project: str, issue: str, by: Actor, reason: str = "")
4279
4485
  # what was delivered. So nobody chooses: finished work closes as delivered, everything else
4280
4486
  # as not.
4281
4487
  delivered = has_finished(stage.key)
4488
+ if kind:
4489
+ return await _by_the_product_role(proj, issue, by=by, reason=said, remove=False,
4490
+ delivered=delivered, vouched=True)
4282
4491
 
4283
4492
  def _close() -> None:
4284
4493
  # THROUGH THE PORT'S OWN SEAM, NOT `tracker.close_ticket(...)` WITH A `TypeError` FALLBACK
@@ -4303,6 +4512,101 @@ async def _card_close(*, project: str, issue: str, by: Actor, reason: str = "")
4303
4512
  project=proj.name, issue=str(issue), delivered=delivered)
4304
4513
 
4305
4514
 
4515
+ async def _card_remove(*, project: str, issue: str, by: Actor, reason: str = "") -> Outcome:
4516
+ """Remove a card nobody has started from the board, with a reason (#384).
4517
+
4518
+ THE CHEAPEST MOMENT TO DROP WORK HAD NO VERB. A card in Backlog that nobody has picked up, filed
4519
+ wrong or twice or no longer wanted, could only be CLOSED — kept in the tracker's history as
4520
+ withdrawn, counted by triage, shown on every list that includes closed cards. This is the
4521
+ removal, and it is allowed only where it cannot hide anything: before pickup (`_stage_refusal`
4522
+ with `act="remove"`); after it, the close is the verb, and the refusal says so.
4523
+
4524
+ WHAT "REMOVE" MEANS IS THE TRACKER ROW'S (`tracker/base.py::remove_ticket`): the local board
4525
+ deletes the card, never reuses its number and keeps an audit line; a row with no removal of its
4526
+ own closes it as not delivered, and this answer says the card stays in that tracker's history.
4527
+ A card the product role opened is removed THROUGH the role (`_by_the_product_role`)."""
4528
+ import asyncio
4529
+
4530
+ proj, tracker, board, bad = _board_pair(project)
4531
+ if bad:
4532
+ return bad
4533
+ said = (reason or "").strip()
4534
+ if not said:
4535
+ return refused(INVALID, "say why the card is being removed — the reason is what the audit "
4536
+ "keeps, and one made only of spaces says nothing.")
4537
+ kind, unreadable = await asyncio.to_thread(_opened_by, tracker, issue)
4538
+ if unreadable:
4539
+ return refused(CONFLICT, unreadable)
4540
+ _stage_at, refusal = await _withdraw_refusal(proj, board, issue, remove=True)
4541
+ if refusal:
4542
+ return refused(CONFLICT, refusal)
4543
+ if kind:
4544
+ return await _by_the_product_role(proj, issue, by=by, reason=said, remove=True,
4545
+ delivered=False, vouched=True)
4546
+
4547
+ def _remove() -> bool:
4548
+ from openfactory.adapters.tracker.base import remove_ticket
4549
+ from openfactory.product.voice import card_close_note
4550
+
4551
+ ticket = tracker.get_ticket(issue)
4552
+ if (getattr(ticket, "state", "") or "open") != "open":
4553
+ raise _AlreadyClosed(issue)
4554
+ note = card_close_note(who=str(by), reason=said,
4555
+ language=getattr(proj, "language", None))
4556
+ return remove_ticket(tracker, issue, said, by=str(by), note=note)
4557
+
4558
+ try:
4559
+ removed = await asyncio.to_thread(_remove)
4560
+ except _AlreadyClosed:
4561
+ return refused(CONFLICT, f"{issue} is already closed — there is nothing on the board to "
4562
+ f"remove. Nothing was changed.")
4563
+ except Exception as exc: # noqa: BLE001 — see `_card_create`
4564
+ return refused(UNAVAILABLE, f"{issue} is still on the board: {exc}")
4565
+ how = ("it is gone from the board, its number will not be used again, and who removed it, "
4566
+ "when and why is kept" if removed else
4567
+ "this tracker can only close a card, so it was closed as not delivered and stays in "
4568
+ "the tracker's history")
4569
+ return done(f"removed {issue} ({by}) — {how}", project=proj.name, issue=str(issue),
4570
+ removed=removed)
4571
+
4572
+
4573
+ class _AlreadyClosed(Exception):
4574
+ """A removal asked of a card that is no longer open — an answer, not a failure."""
4575
+
4576
+
4577
+ def card_view(proj, tracker, board, ref: str, *, opened_by: str, column: str | None = None,
4578
+ state: str = "open") -> dict:
4579
+ """What a card's close and remove controls need to know, for BOTH surfaces (#384): whether the
4580
+ factory has taken the card up, whether it finished it, whether this tracker REMOVES or can only
4581
+ close, and the words the controls and the sentence under the card carry, in the project's
4582
+ language (`voice.card_controls`).
4583
+
4584
+ `started` IS A HINT TO THE PAGE, NEVER THE GATE. It spares a person a button the row would
4585
+ refuse; the row asks the board again when the button is pressed (`_withdraw_refusal`). A column
4586
+ this platform does not map reads as not started here, and the row refuses it by name."""
4587
+ from openfactory.adapters.board.base import stage_key
4588
+ from openfactory.adapters.board.columns import has_finished, has_started
4589
+ from openfactory.adapters.tracker.base import removes
4590
+ from openfactory.contracts.refs import canonical_ref
4591
+ from openfactory.product.voice import card_controls
4592
+
4593
+ if column is None and board is not None:
4594
+ try:
4595
+ placed = board.columns() or {}
4596
+ except Exception: # noqa: BLE001 — a hint, not a gate
4597
+ log.info("could not read where %s is to draw its controls — the row asks again when "
4598
+ "one is pressed", ref, exc_info=True)
4599
+ placed = {}
4600
+ column = placed.get(canonical_ref(ref)) or placed.get(str(ref)) or ""
4601
+ key = stage_key(board, column) if (board is not None and column) else ""
4602
+ started = has_started(key)
4603
+ can_remove = removes(tracker)
4604
+ return {"started": started, "finished": has_finished(key), "removes": can_remove,
4605
+ "open": (state or "open") == "open",
4606
+ "words": card_controls(opened_by_product=bool(opened_by), started=started,
4607
+ removes=can_remove, language=getattr(proj, "language", None))}
4608
+
4609
+
4306
4610
  async def _card_reopen(*, project: str, issue: str, by: Actor) -> Outcome:
4307
4611
  """Put a closed card back — the undo a close on the only surface an operator has must have."""
4308
4612
  import asyncio
@@ -5818,6 +6122,17 @@ CATALOG: dict[str, ActionSpec] = {
5818
6122
  "Done, which is finished work left open and is closed AS delivered. The "
5819
6123
  "card's column decides which, never the caller",
5820
6124
  ),
6125
+ ActionSpec(
6126
+ name="card_remove",
6127
+ summary="remove a card nobody has started from the board, with a reason",
6128
+ run=_card_remove,
6129
+ required=("project", "issue", "reason"),
6130
+ choose_when="when a card should never have been on the board and the factory has not "
6131
+ "taken it up — filed wrong, filed twice, no longer wanted. What removal "
6132
+ "means is the tracker's: the local board deletes it and keeps who, when "
6133
+ "and why; a tracker that can only close closes it and says so. Once the "
6134
+ "factory has the card this refuses, and `card_close` is the verb",
6135
+ ),
5821
6136
  ActionSpec(
5822
6137
  name="card_reopen",
5823
6138
  summary="put a closed card back on the board",
@@ -6017,7 +6332,7 @@ CATALOG: dict[str, ActionSpec] = {
6017
6332
  summary="answer a proposal the product role staged — the pair of product_pending",
6018
6333
  run=_product_answer,
6019
6334
  required=("project", "token", "answer"),
6020
- optional=("yes",),
6335
+ optional=("yes", "message_id"),
6021
6336
  ),
6022
6337
  # ONE ROW FOR THE CONVERSATION (#266 slice 2): `product_ask` and `product_say` were two
6023
6338
  # halves of it, and the panel held the half that could not hear a typed yes.
@@ -6155,6 +6470,33 @@ CATALOG: dict[str, ActionSpec] = {
6155
6470
  required=("project", "number"),
6156
6471
  optional=("in_favour_of", "reason", "yes"),
6157
6472
  ),
6473
+ ActionSpec(
6474
+ name="product_board",
6475
+ scope=PRODUCT,
6476
+ summary="the open cards on the board, and one card with what its controls do",
6477
+ run=_product_board,
6478
+ required=("project",),
6479
+ optional=("card",),
6480
+ params={"card": "the number of the one card to open, digits only — its text and what "
6481
+ "its controls do come back with the list"},
6482
+ needs_admin=False,
6483
+ ),
6484
+ ActionSpec(
6485
+ name="product_withdraw_card",
6486
+ scope=PRODUCT,
6487
+ summary="close a card, or remove one nobody has started, from the card itself",
6488
+ run=_product_withdraw_card,
6489
+ required=("project", "number", "reason"),
6490
+ optional=("remove",),
6491
+ params={"remove": "`true` to remove the card instead of closing it — only before the "
6492
+ "factory takes it up, and what removal means is the tracker's"},
6493
+ # THE MODULE DECIDES WHO (#384): a product admin, or the person who asked for the card
6494
+ # — and the second is on no allowlist, so `needs_admin` would refuse them first.
6495
+ needs_admin=False,
6496
+ choose_when="when a person on the product view drops a card from the card itself — "
6497
+ "the conversation's own close is `product_close_card`, staged and "
6498
+ "confirmed there",
6499
+ ),
6158
6500
  ActionSpec(
6159
6501
  name="product_correct_card",
6160
6502
  scope=PRODUCT,
@@ -152,6 +152,16 @@ class JudgmentAgentAdapter(Protocol):
152
152
  MAX_ARG_STRLEN = 32 * 4096
153
153
 
154
154
 
155
+ #: Harness KINDS whose CLI cannot read a prompt it did not get as an argument — so the staging
156
+ #: channel (#326) does not help them, and a corpus past `MAX_ARG_STRLEN` is undeliverable even on a
157
+ #: box that stages. Today only `kimi` (`kimi-code`): its `-p/--prompt` takes a value and no code
158
+ #: path reads stdin into the prompt, so its adapter keeps the prompt on argv (`stage_prompt(...,
159
+ #: channel=…)` reads THIS set, and `kimi.py` asks it too). ONE PLACE, so the refusal the run raises,
160
+ #: the argument form kimi keeps, and the note `doctor`/`box prove` print before any pickup cannot
161
+ #: drift apart. When `kimi-code` grows a stdin or file form, drop it from here.
162
+ HARNESSES_WITHOUT_STAGED_PROMPT = frozenset({"kimi"})
163
+
164
+
155
165
  #: What the rest of the command costs — the harness's absolute path, the flags, the model, the
156
166
  #: session id. Held back from the ceiling so the check measures the argument the shell will
157
167
  #: actually carry, with room for what is built around the prompt (review of #360).
@@ -53,6 +53,7 @@ import re
53
53
  import shlex
54
54
 
55
55
  from openfactory.adapters.agent.base import (
56
+ HARNESSES_WITHOUT_STAGED_PROMPT,
56
57
  PLANNER_FALLBACK,
57
58
  REPAIR_INSTRUCTION,
58
59
  AgentContext,
@@ -218,9 +219,10 @@ class KimiAdapter:
218
219
  # no code path reads stdin into the prompt. So the prompt stays the argument that was
219
220
  # verified, and the ceiling is still asked — a corpus past it parks with a sentence
220
221
  # instead of dying with `Errno 7`. When `kimi-code` grows a stdin or file form, drop
221
- # `channel=False` and this row joins the others.
222
+ # `channel=False` and this row joins the others — dropping this kind from
223
+ # `HARNESSES_WITHOUT_STAGED_PROMPT`, the one place that fact lives.
222
224
  prompt_path = stage_prompt(sandbox, workspace, prompt, phase=phase, project=project,
223
- channel=False)
225
+ channel=self.name not in HARNESSES_WITHOUT_STAGED_PROMPT)
224
226
  except PromptTooLarge as exc:
225
227
  return prompt_too_large_result(exc, model=model, harness=self.name)
226
228
  command = self._cli(prompt, harness=sandbox.harness_path("kimi"),
@@ -218,6 +218,9 @@ HUMAN_PHASES: frozenset[str] = frozenset({
218
218
  # already carries the requirement's own words around them — an English block between two
219
219
  # Portuguese ones reads as two different people wrote the ticket
220
220
  "product_align",
221
+ # THE CARD A PERSON ASKED FOR (#383): the draft is the card the client opens, and the judge's
222
+ # `ask` is the question the role puts to the person when the card cannot be filed yet
223
+ "product_card_draft", "product_card_judge",
221
224
  })
222
225
 
223
226
  def needs_language_directive(phase: str) -> bool: