{
  "schema": "durable-workflow.v2.platform-conformance.runtime-scenarios",
  "category": "workflow_lifecycle_contract",
  "suite_schema": "durable-workflow.v2.platform-conformance.suite",
  "suite_version": 18,
  "result_schema": "durable-workflow.v2.workflow-lifecycle.result",
  "required_run_record_fields": [
    "artifact_versions",
    "published_artifact_versions",
    "artifact_sources",
    "started_at",
    "finished_at",
    "generated_at",
    "outcome",
    "runner_blocked",
    "scenario_results",
    "lifecycle_cell_outcomes",
    "findings",
    "local_product_source_checkouts_used",
    "source_policy"
  ],
  "required_scenarios": [
    "continue_as_new_run_chain_visibility",
    "continue_as_new_identity_and_history_continuity",
    "continue_as_new_duplicate_side_effect_prevention",
    "cancellation_public_surface_terminal_state",
    "termination_public_surface_terminal_state",
    "workflow_id_reuse_duplicate_start_policy",
    "workflow_timeout_terminal_state",
    "workflow_retry_backoff_or_refusal",
    "php_sdk_lifecycle_surface",
    "python_sdk_lifecycle_surface",
    "rust_sdk_lifecycle_surface",
    "operator_diagnostics_surfaces"
  ],
  "scenarios": [
    {
      "id": "continue_as_new_run_chain_visibility",
      "description": "Continue-as-new creates a visible run chain under one logical workflow id, with distinct run ids and monotonic run numbers.",
      "required_evidence": ["workflow_id", "initial_run_id", "continued_run_id", "run_count", "current_run_id", "run_numbers"],
      "required_behavior": "continue_as_new_creates_a_visible_run_chain_under_one_logical_workflow_id"
    },
    {
      "id": "continue_as_new_identity_and_history_continuity",
      "description": "History and run-list surfaces link the predecessor and successor runs without losing logical workflow identity.",
      "required_evidence": ["workflow_id", "history_events", "predecessor_closed_event", "successor_started_event", "history_api_links"],
      "required_behavior": "history_surfaces_link_predecessor_and_successor_runs_without_losing_logical_identity"
    },
    {
      "id": "continue_as_new_duplicate_side_effect_prevention",
      "description": "Replay, restart, and continue-as-new boundaries do not duplicate externally visible side effects.",
      "required_evidence": ["workflow_id", "side_effect_key", "expected_count", "observed_count", "replay_or_restart_window"],
      "required_behavior": "continue_as_new_replay_or_restart_does_not_duplicate_side_effects"
    },
    {
      "id": "cancellation_public_surface_terminal_state",
      "description": "Cancellation requested through public surfaces reaches a documented terminal state and produces typed observable errors for workers and callers.",
      "required_evidence": ["workflow_id", "request_surface", "cancel_requested_at", "terminal_status", "worker_error_type", "caller_error_type"],
      "terminal_states": ["cancelled"],
      "required_behavior": "public_cancellation_reaches_cancelled_and_surfaces_typed_worker_and_caller_errors"
    },
    {
      "id": "termination_public_surface_terminal_state",
      "description": "Termination requested through public surfaces reaches a documented terminal state and produces typed observable errors for workers and callers.",
      "required_evidence": ["workflow_id", "request_surface", "terminate_requested_at", "terminal_status", "worker_error_type", "caller_error_type"],
      "terminal_states": ["terminated"],
      "required_behavior": "public_termination_reaches_terminated_and_surfaces_typed_worker_and_caller_errors"
    },
    {
      "id": "workflow_id_reuse_duplicate_start_policy",
      "description": "Workflow id reuse and duplicate start policy are enforced or unsupported shapes are refused with a documented typed reason.",
      "required_evidence": ["workflow_id", "duplicate_policy", "first_start_outcome", "first_run_id", "duplicate_start_outcome", "http_status_or_error_type", "run_count_after_duplicate", "run_ids_after_duplicate"],
      "required_behavior": "duplicate_workflow_id_start_fail_policy_refuses_the_duplicate_and_preserves_only_the_first_run"
    },
    {
      "id": "workflow_timeout_terminal_state",
      "description": "Workflow execution or run timeout records operator-visible deadline timing and terminal state.",
      "required_evidence": ["workflow_id", "timeout_field", "deadline_at", "observed_terminal_at", "terminal_status", "operator_visible_timing", "unsupported_timeout_shape_refusals"],
      "required_behavior": "workflow_execution_or_run_timeout_records_deadline_timing_and_terminal_state"
    },
    {
      "id": "workflow_retry_backoff_or_refusal",
      "description": "Workflow-level retry/backoff is proven where supported; unsupported retry cells refuse clearly and match public documentation.",
      "required_evidence": ["workflow_id", "retry_policy_shape", "attempt_count_or_refusal_reason", "backoff_observation_or_error_type", "docs_match"],
      "required_behavior": "workflow_retry_backoff_is_executed_where_supported_or_retry_policy_is_refused_clearly"
    },
    {
      "id": "php_sdk_lifecycle_surface",
      "description": "The exact released durable-workflow/sdk package drives a real PHP client and a separate PHP worker process against the matching public server image.",
      "actors": ["sdk-php"],
      "required_evidence": ["sdk", "covered_cells", "unsupported_cells", "typed_errors", "artifact_version", "server_version", "install_provenance", "apache_avro_provenance", "client_processes", "worker_processes", "callback_counts", "history_assertions", "local_product_source_checkouts_used"],
      "required_behavior": "php_sdk_exercises_supported_lifecycle_cells_or_refuses_unsupported_cells_with_typed_errors"
    },
    {
      "id": "python_sdk_lifecycle_surface",
      "description": "The published Python SDK can exercise supported lifecycle cells, or unsupported cells produce documented typed errors.",
      "required_evidence": ["sdk", "covered_cells", "unsupported_cells", "typed_errors", "artifact_version"],
      "required_behavior": "python_sdk_exercises_supported_lifecycle_cells_or_refuses_unsupported_cells_with_typed_errors"
    },
    {
      "id": "rust_sdk_lifecycle_surface",
      "description": "The exact released Rust SDK crate exercises lifecycle behavior against the matching published server image with official Avro payload provenance, including immutable predecessor decisions across continue-as-new completion redelivery and worker-process replacement.",
      "required_evidence": ["sdk", "covered_cells", "unsupported_cells", "typed_errors", "artifact_version", "server_version", "server_cluster_info", "install_provenance", "workflow_identities", "scenario_outcomes", "stable_reasons", "payload_contract", "executor_topology", "rust_shard_contract_version", "shard_runner", "shard_exit_status"],
      "required_behavior": "rust_sdk_exact_crate_exercises_lifecycle_and_preserves_committed_predecessor_decisions_across_continue_as_new_redelivery_and_worker_process_replacement"
    },
    {
      "id": "operator_diagnostics_surfaces",
      "description": "CLI, API, history, and Waterline-visible state expose enough information for operators and agents to diagnose every lifecycle transition.",
      "required_evidence": ["workflow_id", "cli_fields", "api_fields", "history_fields", "waterline_fields", "diagnostic_transition_matrix"],
      "required_behavior": "cli_api_history_and_waterline_expose_enough_state_to_diagnose_every_lifecycle_transition"
    }
  ],
  "source_policy": {
    "pass_requires_published_artifacts_only": true,
    "local_product_source_checkouts_used_must_be_false": true,
    "truthy_values_rejected": ["1", "true", "yes", "on"]
  }
}
