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.
- {openfactory-0.4.0/openfactory.egg-info → openfactory-0.4.2}/PKG-INFO +1 -1
- {openfactory-0.4.0 → openfactory-0.4.2}/README.md +1 -1
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/__init__.py +1 -1
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/actions/catalog.py +378 -36
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/base.py +10 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/kimi.py +4 -2
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/roles.py +3 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/azure_devops.py +159 -59
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board_db.py +25 -3
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/credential/registry.py +86 -13
- openfactory-0.4.2/openfactory/adapters/credential/short_lived.py +69 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/sandbox/container.py +108 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/sandbox/worktree.py +17 -3
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/base.py +107 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/local.py +86 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/api/app.py +51 -6
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/api/panel.html +245 -43
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/api/product_chat.py +45 -12
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/box_prove.py +52 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/cli.py +9 -1
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/project.py +5 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/ticket.py +5 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/credentials.py +170 -3
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/doctor.py +226 -4
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/factory.py +10 -3
- openfactory-0.4.2/openfactory/gate_seal.py +150 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/memory/transcript.py +71 -2
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/observability/metrics.py +3 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/deployment.py +33 -2
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/orchestrator/context.py +90 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/orchestrator/machine.py +24 -5
- openfactory-0.4.2/openfactory/org_defaults/cards/defect-template.md +23 -0
- openfactory-0.4.2/openfactory/org_defaults/cards/rubric.yaml +140 -0
- openfactory-0.4.2/openfactory/org_defaults/cards/template.md +23 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/__init__.py +2 -1
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/demand.py +51 -5
- openfactory-0.4.2/openfactory/preview/live.py +179 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/siblings.py +7 -4
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/steps.py +3 -3
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/agenda.py +42 -20
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/attachments.py +48 -16
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/authoring.py +31 -9
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/board.py +35 -1
- openfactory-0.4.2/openfactory/product/cards.py +888 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/case.py +21 -3
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/confirm.py +40 -4
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/door.py +6 -2
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/engine.py +288 -46
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/events.py +171 -27
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/model.py +14 -8
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/module.py +333 -44
- openfactory-0.4.2/openfactory/product/progress.py +73 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/role.py +94 -52
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/voice.py +450 -6
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/review/verdict.py +17 -7
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/boxed_job.py +25 -2
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/repo_cache.py +202 -66
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/activities.py +473 -37
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/conversation.py +67 -10
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/io.py +50 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/view.py +54 -4
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/worker.py +12 -1
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/workflow.py +164 -16
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/techlead/conversation.py +7 -1
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/techlead/voice.py +44 -0
- {openfactory-0.4.0 → openfactory-0.4.2/openfactory.egg-info}/PKG-INFO +1 -1
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory.egg-info/SOURCES.txt +25 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/pyproject.toml +1 -1
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_card_is_closed_only_when_its_work_merges.py +3 -2
- openfactory-0.4.2/tests/test_a_card_is_drafted_and_judged_before_the_yes.py +1010 -0
- openfactory-0.4.2/tests/test_a_card_nobody_started_can_be_closed_and_removed.py +573 -0
- openfactory-0.4.2/tests/test_a_clicked_yes_is_answered_once.py +316 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_credential_is_scoped.py +2 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_credential_only_goes_to_its_own_host.py +90 -3
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_deployments_addresses_have_one_owner.py +2 -1
- openfactory-0.4.2/tests/test_a_failed_preview_is_said_on_the_card.py +265 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_file_is_attached_in_the_conversation.py +132 -2
- {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
- openfactory-0.4.2/tests/test_a_gate_answer_needs_the_panels_seal.py +243 -0
- openfactory-0.4.2/tests/test_a_hosted_worker_uses_the_identity_its_host_has.py +463 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_large_prompt_travels_off_the_command_line.py +31 -0
- openfactory-0.4.2/tests/test_a_malfunction_is_a_defect_without_a_written_promise.py +63 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_preview_is_started_on_demand.py +27 -2
- openfactory-0.4.2/tests/test_a_preview_starts_itself_when_the_pull_request_opens.py +601 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_product_is_previewed_across_its_repositories.py +3 -2
- openfactory-0.4.2/tests/test_a_proxy_is_not_the_metadata_endpoint.py +265 -0
- openfactory-0.4.2/tests/test_a_pull_request_lives_in_the_forges_repository.py +253 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_re_run_keeps_every_value_the_file_holds.py +27 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_refusal_is_not_an_answer.py +3 -1
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_rejected_review_can_be_asked_again.py +1 -1
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_resume_re_enters_the_merge.py +7 -6
- openfactory-0.4.2/tests/test_a_retried_turn_records_the_message_once.py +282 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_stream_ends_when_its_credential_does.py +23 -3
- openfactory-0.4.2/tests/test_a_test_leaves_the_environment_as_it_found_it.py +57 -0
- openfactory-0.4.2/tests/test_a_turn_says_what_it_is_doing_while_the_person_waits.py +501 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_vendor_error_code_is_not_a_status.py +4 -1
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_accepting_what_the_code_already_does_files_nothing.py +11 -5
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_card_maintenance.py +1 -1
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_corpus_health_and_board_placement.py +1 -1
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_events_and_the_agenda.py +28 -8
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_every_source_is_mounted.py +153 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_everyone_who_opens_a_door_asks_the_one_gate.py +8 -2
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_no_unbounded_growth.py +11 -0
- openfactory-0.4.2/tests/test_nothing_is_published_beyond_this_machine.py +65 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_only_a_blocking_build_failure_is_broken_code.py +4 -3
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_repo_cache_lifecycle.py +104 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_sweep_client_surface.py +7 -1
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_temporal_workflow.py +126 -7
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_action_layer.py +7 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_ado_credential_outlives_one_token.py +7 -7
- openfactory-0.4.2/tests/test_the_board_a_reader_sees_is_the_board_on_disk.py +256 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_board_is_a_page_on_the_panel.py +10 -11
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_deployment_asks_the_rows_for_their_variables.py +2 -1
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_forge_credential_is_per_project.py +24 -5
- openfactory-0.4.2/tests/test_the_inlined_document_bytes_are_reported.py +243 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_installer_builds_the_commands_it_says_it_does.py +98 -4
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_merge_gate_is_heard_on_every_path.py +86 -9
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_merge_is_the_end_of_the_road.py +3 -2
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_one_door.py +1 -1
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_one_machine_deployment_runs_unattended.py +16 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_oss_distribution.py +15 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_is_a_chat.py +9 -3
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_owner_opens_a_card_as_described.py +1 -1
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_role_lives_outside_slack.py +7 -2
- openfactory-0.4.2/tests/test_the_requester_hears_the_change_is_theirs_to_try.py +424 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_suite_runs_where_a_maintainer_sits.py +32 -6
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_techlead_can_see_what_it_reasons_about.py +1 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_web_offers_the_room_and_the_private_chat.py +3 -1
- {openfactory-0.4.0 → openfactory-0.4.2}/LICENSE +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/NOTICE +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/actions/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/actions/base.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/actions/floor_intents.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/claude_code.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/codex.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/opencode.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/registry.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/routes.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/session_store.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/stream.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/techlead.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/agent/token_pool.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board/azure_devops.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board/base.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board/columns.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board/factory.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board/jira.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board/local.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board_setup/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board_setup/base.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board_setup/local.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/board_setup/registry.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/channel/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/channel/base.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/channel/panel.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/channel/registry.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/credential/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/embed/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/embed/base.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/embed/local.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/embed/registry.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/environment/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/environment/azure_pipelines.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/environment/base.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/environment/github_actions.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/environment/none.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/environment/registry.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/base.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/mail.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/markup.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/model.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/office.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/pdf.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/registry.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/text.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/extract/vision.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/forge/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/forge/azure_devops.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/forge/base.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/forge/github.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/forge/local.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/forge/registry.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/github_app.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/notify/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/notify/base.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/notify/panel.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/notify/registry.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/preview/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/preview/base.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/preview/compose.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/preview/none.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/preview/registry.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/reviewer/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/reviewer/base.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/reviewer/claude_code.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/reviewer/harness.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/sandbox/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/sandbox/base.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/sandbox/registry.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/sandbox/timeouts.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/azure_devops.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/github.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/github_board_setup.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/github_project.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/jira.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/parse.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/adapters/tracker/registry.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/after_merge.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/agent_answer.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/api/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/api/metrics_view.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/approvals.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/cli_refusals.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/conformance/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/conformance/adapters.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/aliases.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/bot.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/checks.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/commands.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/decision.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/document.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/item_space.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/manifest.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/product.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/profile.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/refs.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/review.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/run.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/contracts/state.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/doors.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/environ.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/floor/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/floor/ladder.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/floor/reading.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/identity/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/identity/base.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/identity/local.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/identity/oidc.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/identity/people.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/identity/registry.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/bundle.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/check.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/contracts.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/experiment.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/flows.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/gaps.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/gate.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/gather.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/generator.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/inventory.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/okf.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/pipeline.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/render.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/requests.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/service.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/staleness.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/adrs.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/contracts.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/deployments.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/derive.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/interfaces.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/refresh.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/render.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/schemas.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/text.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/knowledge/system/tree.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/language/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/language/assent.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/listeners.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/loader.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/memory/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/memory/ledger.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/memory/messages.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/memory/recall.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/memory/store.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/namespace.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/observability/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/observability/events.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/observability/job_record.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/observability/query.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/observability/registry.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/observability/sqlite_metrics.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/observability/trajectory.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/concepts.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/context.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/cover.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/firstrun.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/history.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/infer.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/live_ci.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/onboard.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/preview_infer.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/preview_product.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/preview_propose.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/propose_manifest.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/questions.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/readiness.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/renew.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/onboarding/spend.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/ops/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/ops/impediment.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/orchestrator/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/orchestrator/errors.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/orchestrator/merge_policy.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/orchestrator/operator_guidelines.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/orchestrator/promotion.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/orchestrator/risk.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/orchestrator/validation.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/engineering.md +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/floor.yaml +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/profiles/prototype.yaml +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/profiles/regulated.yaml +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/requirements/0000-template.md +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/roles/coordinator.md +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/roles/executor.md +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/roles/planner.md +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/roles/product.md +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/roles/recovery.md +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/roles/sizer.md +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/roles/techlead.md +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/org_defaults/tdd.md +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/own_work.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/paths.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/plugins.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/authz.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/census.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/conformance.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/context_writes.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/floor.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/presets.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/profiles.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/protected.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/policy/test_work.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preflight.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/presets/node.yaml +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/presets/python.yaml +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/presets/security-oss.yaml +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/presets/terraform.yaml +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/admit.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/assemble.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/plan.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/product.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/read.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/reap.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/preview/unit.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/addressing.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/asked.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/briefing.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/brownfield.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/cap.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/capabilities.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/chain.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/channel.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/clock.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/config.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/conversation.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/corpus.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/distil.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/documents/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/documents/ingest.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/documents/reading.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/documents/record.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/documents/store.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/domain.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/evaluation/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/evaluation/__main__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/evaluation/battery.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/evaluation/run.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/evaluation/score.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/facts.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/followup.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/index/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/index/items.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/index/retrieval.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/index/search.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/index/store.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/index/sync.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/intents.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/key.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/loader.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/needs_action.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/onboard.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/page.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/queue.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/reading.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/release.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/requester.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/semaphore.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/sessions.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/sight.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/sources.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/speaker.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/staging.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/triage.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/product/workspace.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/registry.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/review/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/card_repo.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/host.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/repairable.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/connection.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/poller.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/schedule.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/standing.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/starter.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/temporal/vocabulary.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/runtime/toolbox.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/scheduler.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/semver.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/techlead/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/techlead/classify.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/techlead/diagnosis.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/techlead/memory.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/techlead/pack.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/techlead/watch.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/testing/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/testing/local_flow.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/util/__init__.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/util/bounded.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/util/causes.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/util/filelock.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory/util/scratch.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory.egg-info/dependency_links.txt +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory.egg-info/entry_points.txt +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory.egg-info/requires.txt +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/openfactory.egg-info/top_level.txt +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/setup.cfg +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_banner_line_does_not_kill_the_review.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_budget_nothing_spends_is_not_a_defect.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_card_can_be_previewed.py +0 -0
- {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
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_card_s_base_is_the_base_the_job_starts_from.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_card_says_who_asked_for_it.py +0 -0
- {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
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_case_does_not_outlive_its_test.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_concept_is_earned_not_declared.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_context_repository_is_creatable_on_azure_too.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_count_is_a_number_not_a_sentence.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_credential_is_asked_of_its_own_axis.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_decision_is_written_down.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_declared_environment_is_observed_or_named.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_declined_read_is_said_where_it_is_read.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_delivered_card_is_closed_by_its_tracker.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_delivered_ticket_is_not_rerun.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_deployment_can_run_a_preview.py +0 -0
- {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
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_disabled_project_does_not_look_armed.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_double_without_intake_answers_every_turn.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_failed_board_read_is_not_a_wrong_root.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_failing_check_is_read_for_what_it_is.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_failing_setup_is_not_silent.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_file_nothing_describes_is_the_least_safe_to_change.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_fingerprint_gains_a_reader.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_finished_card_is_closed_as_delivered.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_finished_job_is_never_restarted_from_the_base.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_frame_does_not_erase_what_it_omits.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_free_deployment_can_read_its_logs.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_free_deployment_resumes_its_own_sessions.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_fresh_install_reads_an_empty_store.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_fresh_install_registers_no_projects.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_gate_is_not_a_stall.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_gate_that_could_not_run.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_gate_that_holds_says_so_where_the_person_decides.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_green_deploy_asks_somebody_to_look.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_green_environment_is_green_for_THIS_change.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_guideline_stays_inside_the_repository.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_hostile_value_stays_data.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_human_gate_is_not_a_review.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_jira_project_is_a_board.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_job_branches_from_the_base_the_forge_holds.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_killed_mutation_run_cannot_hide.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_local_deployment_names_no_vendor.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_machine_made_hold_says_its_own_cause.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_manifest_can_be_proven_before_it_is_merged.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_manifest_outside_the_repository_is_not_proposed.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_manifest_that_loads_is_not_a_manifest_that_is_right.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_message_never_claims_an_action_nobody_takes.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_message_only_teaches_a_verb_the_channel_parses.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_model_nobody_can_run_is_not_a_setting.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_name_nobody_registered_is_not_removed.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_named_check_is_not_dropped.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_negation_the_bridge_carries_is_refused.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_pass_in_flight_is_not_a_gate.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_pass_that_changed_nothing.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_path_nothing_declares_is_not_the_freest.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_path_registers_itself.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_paused_factory_says_so.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_paused_pass_is_charged.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_person_has_more_than_one_conversation.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_person_is_invited_not_signed_up.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_personal_accounts_board_is_readable.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_personal_boards_columns_can_be_read.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_poller_that_is_on_is_not_a_poller_that_ticks.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_preexisting_context_repo_is_declarable.py +0 -0
- {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
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_preview_is_ended_by_the_reaper.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_preview_is_proposed_from_what_the_repository_says.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_preview_is_reached_on_one_machine.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_preview_opens_on_one_machine.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_preview_reaches_nothing_of_the_host.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_preview_runs_on_a_real_daemon.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_preview_starts_on_a_real_daemon.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_probe_set_is_pinned_whole.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_process_that_approves_keeps_one_engine_client.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_product_is_its_context_repository.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_project_can_change_the_language_it_speaks_first.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_project_declares_what_it_is.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_project_is_not_registered_as_the_wrong_vendor.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_project_nobody_registered_is_never_a_500.py +0 -0
- {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
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_proof_that_was_not_recorded_says_so.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_proposal_can_carry_what_to_change.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_proposal_whose_base_moved_still_lands_on_the_local_forge.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_proposed_command_can_run_where_the_box_runs_it.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_provider_is_named_by_its_own_row.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_pull_request_is_read_and_merged_in_its_own_repository.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_pull_that_changes_nothing_is_impossible_to_miss.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_question_reaches_the_person_who_asked.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_range_is_a_citation.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_read_that_failed_is_not_an_empty_floor.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_rebuild_is_not_a_change.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_ref_that_is_not_a_number.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_remedy_names_a_document_that_exists.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_repaired_card_is_announced_on_any_tracker.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_repository_on_the_former_name_is_refused_at_every_door.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_retired_pipeline_is_not_a_gate.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_review_belongs_to_the_code_it_read.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_scenario_is_one_criterion.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_scratch_directory_is_the_only_thing_we_delete.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_skip_is_something_that_happened.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_staged_decision_survives_a_refresh.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_staged_proposal_does_not_outlive_its_test.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_store_that_cannot_be_read_authorizes_nobody_and_says_so.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_stranger_can_add_a_role.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_stranger_can_add_an_adapter.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_suite_that_stopped_collecting_is_not_a_green_suite.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_ticket_ref_is_never_typed_as_a_number.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_ticket_written_in_portuguese.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_trust_file_nobody_reads_is_a_green_proof.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_typed_instruction_reaches_the_same_row_as_the_button.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_verb_says_what_to_put_in_it.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_verdict_nobody_answers_is_said_so_inside_the_deadline.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_wait_can_say_until_when.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_wedged_job_has_an_exit.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_wedged_job_is_seen.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_withdrawn_card_is_not_delivered_on_jira.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_withdrawn_card_lands_in_the_sites_own_status_on_jira.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_write_that_did_not_land_is_not_counted.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_a_yes_is_an_answer.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_accept_flows_end_to_end.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_acceptance_loop.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_accepting_starts_the_work.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_acknowledgement.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_adapter_conformance_suite.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_advisory_findings_survive_save.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_agent_harness.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_agent_resume_c2.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_agent_roles.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_agent_stream.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_agent_token_pool.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_already_asked_is_answered_from_the_board_not_the_transcript.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_activity_uses_the_client_its_worker_holds.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_advisory_gate_cannot_hold_a_pickup.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_advisory_gate_reports_and_never_blocks.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_environment_written_before_this_change_still_resolves_the_old_path.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_intake_is_a_typed_case.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_open_question_can_be_retired.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_open_question_is_an_offer_not_a_toll.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_unread_collection_is_not_an_empty_one.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_unread_review_is_not_a_rejection.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_an_unreadable_store_is_not_an_empty_one.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_api.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_auto_merge_is_judged_from_the_gates_that_were_read.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_board_is_vendor_neutral.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_board_read_cost.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_bot_push.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_box_carries_the_provider_kind.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_box_prove.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_breakdown_reuses_what_exists.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_brownfield_wired.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_c18_has_an_azure_expression.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_c18_reaches_every_entry_point.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_capabilities_and_checks.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_card_maintenance_channel.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_causes.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_ci_runs_what_we_run.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_client_board_is_not_a_test_bench.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_commit_workflow_strip.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_compose_forwards_the_whole_env_file.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_confirmation_by_click.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_confirmation_is_understood.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_context.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_conversation_worlds.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_create_repository_survives_an_app_token.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_decision.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_decision_loop.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_deploy_watch_workflow.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_diff_hygiene.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_doctor.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_doctor_checks_the_product_link.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_env_apply_answers_in_the_readers_language.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_env_apply_takes_a_path_like_env_read.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_env_proposes_before_it_verifies.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_event_sinks.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_every_FROM_the_release_builds_resolves_without_the_local_daemon.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_every_image_the_compose_file_names_is_one_the_release_builds.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_every_mutation_plan_can_run.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_factory_asks_for_help.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_filed_work_is_reachable.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_first_real_conversation.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_forge_ci.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_forge_deploy.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_forge_idempotency.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_foundation.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_gh_is_authenticated.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_handoff.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_init_asks_for_one_machine.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_init_generates_the_deployment.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_init_speaks_to_the_operator_not_to_us.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_init_that_acts.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_internal_imports_resolve.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_judge_verdict_parsing.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_kernel_names_no_vendor.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_knowledge.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_knowledge_build_reaches_a_factory_cloned_project.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_knowledge_derived_not_cached.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_knowledge_experiment.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_knowledge_pipeline.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_local_flow.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_loops_are_reachable.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_manifest_version.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_memory_ledger.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_memory_recall_eval.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_memory_store.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_merge_policy.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_metrics.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_no_card_id_reaches_a_stranger.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_no_checkout_assumes_a_branch_name.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_no_front_end_pays_for_the_engines_client_by_accident.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_no_gesture_exists_in_one_language_only.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_no_module_is_ever_called_like_a_function.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_no_plumbing_reaches_the_client.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_no_silent_failures.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_no_vendor_in_the_core.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_non_numeric_refs_reach_the_api.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_nothing_speaks_before_it_asks_the_language.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_observability_registries.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_office_documents_are_read.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_onboard_builds_the_context_too.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_onboard_proposes_a_measured_setup.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_onboarding_a_context_that_already_exists.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_onboarding_backfills_the_context.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_onboarding_creates_the_context_repository.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_onboarding_firstrun.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_one_author_writes_the_close_of_a_repair_brief.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_one_author_writes_the_order_of_a_recovery_and_a_resume.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_one_cost_for_a_ticket_on_every_surface.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_one_memory_per_product.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_one_process_one_installation.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_one_question_decides_where_the_factory_runs.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_one_turn_engine.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_opencode_harness.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_operator_guidelines.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_orphaned_cards_are_repointed.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_panel_approval_store.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_panel_reads_events_without_aws.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_park_alert.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_paths_are_traversal_safe.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_permission_is_an_order_in_every_language.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_ports_are_serialisable.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_preflight.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_preflight_json_is_the_document_the_agent_lane_reads.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_preflight_names_a_remedy_for_every_thing_it_refuses.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_preflight_says_which_machine_it_measured.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_authoring.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_board_reads.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_brownfield.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_channel.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_config.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_corpus.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_followup.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_followup_e2e.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_init_writes_a_file_its_own_check_accepts.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_intents.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_loader.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_module.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_needs_action.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_role.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_sees_the_code.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_simulation.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_sweep.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_triage.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_view_is_stable.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_voice.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_product_workspace.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_project_add_exposes_language.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_project_add_speaks_azure_devops.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_promotion.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_provenance_in_the_brief.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_provider_seams.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_public_core_names_no_forge.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_recent_runs_outlives_the_engine.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_registry_is_runtime_state.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_repo_cache_credentials.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_requirement_can_be_dropped.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_requirement_lifecycle.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_sandbox_registry.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_scheduler.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_schedules_are_reachable.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_somebody_is_asked_to_look_at_what_shipped.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_something_finally_asks_the_agent.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_sqlite_metrics.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_sso_is_a_row_the_core_ships.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_sweep_records_only_what_posted.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_techlead_classify.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_techlead_memory.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_techlead_self_heal.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_techlead_watch.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_telemetry_reads_from_the_configured_sink.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_temporal_call_arity.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_temporal_view.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_acceptance_map_reaches_a_person.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_add_on_packages_install.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_ado_board.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_ado_coordinates_have_one_home.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_ado_forge.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_ado_pipelines.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_ado_tracker.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_alert_names_its_ticket_on_any_tracker.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_announcement_carries_the_verdict.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_app_key_reaches_every_entry_point.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_app_permission_table_has_one_home.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_approver_verbs_ask_which_store_is_in_force.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_areas_that_change_are_the_ones_that_matter.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_attended_driver_records_what_it_spent.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_backfill_is_metered.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_backfill_names_the_real_reason.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_backfill_reads_every_source.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_backfills_questions_can_be_finished.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_base_branch_is_asked_not_assumed.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_bench_is_not_the_case.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_board_keeps_your_place.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_board_lives_in_one_file.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_board_names_its_own_pickup_column.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_board_port_takes_any_providers_ref.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_board_row_says_which_stage_its_column_is.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_board_says_where_it_lives.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_can_obtain_the_repository.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_can_reach_the_pr_branch.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_claims_only_what_it_does.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_clones_from_the_forge_it_was_told.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_does_not_run_the_clients_shell_profile.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_env_is_a_named_seam.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_image_resolves_in_one_place.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_image_the_worker_spawns_is_one_the_install_pulls.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_program_can_be_launched.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_proof_is_watchable.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_says_where_the_harness_is.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_says_where_the_operator_guidelines_are.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_takes_text_the_command_line_never_carries.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_box_transmits_while_it_runs.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_boxed_job_entrypoint.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_branch_carries_the_products_name.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_briefing.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_budget_read_leaves_the_panels_loop.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_button_without_a_gate.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_card_carries_ONE_acceptance_section.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_card_moves_even_when_the_link_cannot_be_built.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_card_says_what_the_floor_says.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_chat_has_its_own_fences.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_chat_is_a_directory_delete.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_chat_thread_survives_a_refresh.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_ci_is_read_more_than_once.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_cli_refuses_in_sentences.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_cli_runs_in_the_deployments_box.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_client_never_reads_an_emoji.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_client_releases_production.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_cloud_is_a_directory_delete.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_columns_and_the_identity_are_the_platforms.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_compose_file_can_be_installed_and_built_from_one_file.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_compose_row_runs_what_was_admitted.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_confirmation_executor.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_context_proposal_is_reachable.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_context_repository_can_be_created.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_context_repository_exists_on_this_runtime.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_conversation_is_pinned.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_core_addon_ledger.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_core_boundary.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_core_does_not_need_a_cloud.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_core_is_a_core.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_core_names_no_vendor.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_credential_scan_reads_a_delimiter.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_default_language_is_the_products.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_diff_decides_scope_and_what_validates.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_distribution_ships_what_it_tells_you_to_copy.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_docs_do_not_drift.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_docs_name_no_vendor_as_the_core.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_docs_say_which_promise.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_doctor_names_the_gates_only_a_person_settles.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_doctor_names_the_operator_guidelines.py +0 -0
- {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
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_doctor_says_how_the_product_reads.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_doctor_says_where_project_less_speech_goes.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_doctor_survives_its_own_probes.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_doctor_tells_the_truth_about_this_machine.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_documentation_has_one_front_door.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_documented_default_is_the_real_one.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_documents_are_read.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_documents_are_read_on_the_schedule_and_on_an_event.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_documents_describe_the_product_this_tree_is.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_documents_name_the_repository_and_keep_their_accents.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_doors_derive_from_the_registries.py +0 -0
- {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
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_engine_answers_or_says_so.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_engine_dying_under_a_job_is_not_a_mystery.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_engine_starts_only_beside_the_library_its_worker_runs_on.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_environment_carries_the_products_name.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_environment_round_is_a_terminal_verb.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_evaluation_battery.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_event_axis_is_reached.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_examples_a_reader_copies_load_on_the_core.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_extensibility_doc_names_the_real_group.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_extra_ca_file_is_always_a_valid_pem.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_factory_asks_before_it_starts.py +0 -0
- {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
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_factory_runs_on_one_machine.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_factory_runs_without_a_cloud.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_facts_are_files_the_techlead_can_open.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_facts_stay_files_for_every_harness.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_first_hour_fails_by_name.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_first_round_is_reachable.py +0 -0
- {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
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_floor_and_the_inbox_agree.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_floor_is_a_deployment_default_not_a_transcription.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_floor_is_a_platform_capability.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_floor_is_enforced_where_the_money_is.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_floor_is_not_re_read_on_every_frame.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_forge_can_read_a_foreign_repository.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_forge_names_a_card_only_in_its_own_words.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_forge_opens_a_pr_in_another_repository.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_form_asks_what_the_address_needs.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_gate_checks_the_shell_script_a_stranger_runs_first.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_gate_holds_when_the_store_cannot_be_read.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_gate_shows_what_the_review_found.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_generated_environment_names_a_work_directory_that_needs_no_root.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_harness_endpoint_is_the_clients.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_harness_is_watched_while_it_runs.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_harness_pulse.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_history_says_where_the_work_is.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_hybrid_index.py +0 -0
- {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
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_installer_knows_exactly_two_facts_the_package_does_not.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_installer_never_calls_sudo.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_installer_pins_a_version_and_never_installs_a_floating_tag.py +0 -0
- {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
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_inventory_counts_what_it_could_not_place.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_journal_is_where_the_deployment_says.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_journal_records_how_a_job_ENDED.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_judging_roles_can_reach_their_model.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_language_reaches_every_unprompted_surface.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_lifecycle_names_no_provider.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_loop_tells_the_truth.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_manifest_can_be_proposed_server_side.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_manifest_reference_is_complete.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_map_does_not_wait_for_a_merge.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_map_is_published_beside_the_concepts.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_map_says_what_it_does_not_cover.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_memory_writes.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_merge_re_authors_what_it_invalidated.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_model_is_a_per_project_choice.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_model_is_set_from_the_cli.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_mutation_runner_is_not_decoration.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_namespace_is_the_products_name.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_net_that_protects_the_client.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_number_told_is_the_number_written.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_open_distribution_has_a_voice.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_operator_hears_the_projects_language.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_operator_path_names_what_the_code_mints.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_holds_one_engine_client.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_is_a_channel.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_is_pushed_to.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_names_no_vendor.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_reads_as_a_control_room.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_says_a_pass_is_running.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_says_where_to_change_things.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_says_whether_work_is_picked_up.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_says_which_harness.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_serves_without_the_engines_client.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_speaks_one_language.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_panel_touches_no_cloud_locally.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_platform_reads_a_repository_and_proposes.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_poller_has_a_lever.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_preview_axis.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_carries_no_ones_past.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_carries_no_owners_name.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_conversation_is_core.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_owner_orders_the_backlog_from_chat.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_owner_reads_an_intake_and_teaches.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_owner_s_page.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_owner_writes_the_backlog_order.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_owners_facts_are_files.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_path_is_not_github_by_construction.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_role_is_called_nina.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_product_role_speaks_the_clients_language.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_project_remembers_what_everyone_said.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_promotion_tail_speaks.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_proof_gates_each_repository.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_proof_gates_pickup.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_proof_on_the_host.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_proposal_covers_the_floor.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_public_cut_is_written_down.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_public_documents_serve_a_stranger.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_pull_request_lives_in_the_file.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_pull_request_says_what_the_card_says.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_pull_request_says_what_the_last_attempt_did.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_queue_proposes_in_batches.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_read_model.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_reading_is_bound_against_the_bundle_that_exists.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_refusal_reads_the_file_it_would_write.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_release_assembles_what_the_installer_downloads.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_remedy_a_refusal_hands_you_can_be_followed.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_renewal_keeps_the_inventory_current.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_repair_brief_states_the_failure_it_was_given.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_repository_moves_to_the_ticket.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_retrieval_step.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_review_findings_stay_fixed.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_review_is_charged_on_every_surface.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_reviewer_can_actually_run.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_role_does_not_claim_blindness.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_role_knows_what_day_it_is.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_roles_can_reach_the_bundle.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_roles_run_on_the_local_rows.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_second_deployment_is_not_the_first.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_second_yes_is_the_requesters.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_security_policy_promises_what_the_scrub_does.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_semaphore_on_work.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_set_ends_together.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_shape_is_read_and_admitted.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_shell_we_ship_runs_on_both_seds.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_sizer_names_the_area_it_expects_to_touch.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_socket_is_real_and_scoped.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_speaker_and_the_reply.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_split_says_which_card_to_drag.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_starter_template_passes_its_own_floor.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_station_strip_resets_on_a_re_run.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_stock_box_runs_what_the_proposer_proposes.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_structural_documents_speak_the_projects_portuguese.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_suite_cannot_reach_a_live_engine.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_suite_cannot_reach_production.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_suite_never_writes_the_registry_your_shell_names.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_system_layer.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_system_layer_is_published.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_techlead_answers_without_a_channel.py +0 -0
- {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
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_techlead_can_see_the_change_it_judges.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_techlead_does_not_cry_wolf.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_techlead_reads_through_the_ports.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_techlead_remembers_the_conversation.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_techlead_sees_a_jira_floor.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_ticket_url_is_the_trackers_own.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_toolbox.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_tracker_has_a_read_side.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_tracker_reads_what_a_person_wrote.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_trajectory_is_a_measurement.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_trajectory_reaches_the_record.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_two_halves_agree_on_which_code_they_run.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_vendors_credential_is_found_by_default.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_verifier_is_not_editable_by_what_it_verifies.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_walk_respects_what_the_repository_ignores.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_web_conversation_is_directed_at_the_person_in_it.py +0 -0
- {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
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_wheel_ships_what_the_platform_needs.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_word_list_is_a_shortcut_not_a_gate.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_the_worker_waits_for_the_engine_to_listen.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_three_commands_one_verdict.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_token_provider.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_tracker_board_writes.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_tracker_is_vendor_neutral.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_transcript_memory.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_two_projects_do_not_share_a_box.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_voice_vocabulary.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_walking_skeleton.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_what_git_refuses_the_person_reads.py +0 -0
- {openfactory-0.4.0 → openfactory-0.4.2}/tests/test_what_the_card_shows_inside_a_bullet_is_what_is_read.py +0 -0
- {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.
|
|
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 (
|
|
213
|
+
| [docs/adr/](docs/adr/) | why it is built this way (54 decision records) |
|
|
214
214
|
|
|
215
215
|
## Status
|
|
216
216
|
|
|
@@ -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
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
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
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
return
|
|
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
|
|
4229
|
-
"""
|
|
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=
|
|
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:
|