



  

<!DOCTYPE html>
<html
  lang="en"
  
  data-color-mode="auto" data-light-theme="light" data-dark-theme="dark"
  data-a11y-animated-images="system" data-a11y-link-underlines="true"
  
  >




  <head>
    <meta charset="utf-8">
  <link rel="dns-prefetch" href="https://github.githubassets.com">
  <link rel="dns-prefetch" href="https://avatars.githubusercontent.com">
  <link rel="dns-prefetch" href="https://github-cloud.s3.amazonaws.com">
  <link rel="dns-prefetch" href="https://user-images.githubusercontent.com/">
  <link rel="preconnect" href="https://github.githubassets.com" crossorigin>
  <link rel="preconnect" href="https://avatars.githubusercontent.com">

<script type="importmap">{"imports":{"react":"https://github.githubassets.com/assets/react-e27d1b3e03961e68.js","react-dom":"https://github.githubassets.com/assets/react-dom-e5fd46a22d5c4058.js","react-dom/client":"https://github.githubassets.com/assets/react-dom-client-1b4a3ee065998cea.js","react-is":"https://github.githubassets.com/assets/react-is-e0b593954b4706d8.js","react-reconciler":"https://github.githubassets.com/assets/react-reconciler-8e99e505c4429605.js","react/compiler-runtime":"https://github.githubassets.com/assets/react-compiler-runtime-4610bd6d3de9c049.js","react/jsx-dev-runtime":"https://github.githubassets.com/assets/react-jsx-dev-runtime-ea55d68667d559e5.js","react/jsx-runtime":"https://github.githubassets.com/assets/react-jsx-runtime-4915cb0f5b3aff04.js","scheduler":"https://github.githubassets.com/assets/scheduler-58b860b049ca307c.js"}}</script>
<meta name="react-profiling" content="0" data-turbo-transient="true" />
<meta name="react-import-map" content="react,react-dom,react-dom/client,react-dom/profiling,react-is,react-reconciler,react/compiler-runtime,react/jsx-dev-runtime,react/jsx-runtime,scheduler@777f63f87cd0" data-turbo-track="reload" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-e27d1b3e03961e68.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-compiler-runtime-4610bd6d3de9c049.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/scheduler-58b860b049ca307c.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-dom-e5fd46a22d5c4058.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-dom-client-1b4a3ee065998cea.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-is-e0b593954b4706d8.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-jsx-runtime-4915cb0f5b3aff04.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-reconciler-8e99e505c4429605.js" />

  


  <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/light-5c4e9fc574bf49f3.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/light_high_contrast-fb37c309e0603a69.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/dark-afff6c53aef9b9d1.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/dark_high_contrast-c409873d7987dffa.css" /><link data-color-theme="light" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light-5c4e9fc574bf49f3.css" /><link data-color-theme="light_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_high_contrast-fb37c309e0603a69.css" /><link data-color-theme="light_colorblind" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_colorblind-0f910d8806d5761b.css" /><link data-color-theme="light_colorblind_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_colorblind_high_contrast-a7abd4d4c49ac593.css" /><link data-color-theme="light_tritanopia" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_tritanopia-5fc4c4a9cb41e596.css" /><link data-color-theme="light_tritanopia_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_tritanopia_high_contrast-ed0cee9214dedabd.css" /><link data-color-theme="dark" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark-afff6c53aef9b9d1.css" /><link data-color-theme="dark_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_high_contrast-c409873d7987dffa.css" /><link data-color-theme="dark_colorblind" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_colorblind-78a2491d538dab5a.css" /><link data-color-theme="dark_colorblind_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_colorblind_high_contrast-c26b63d7c532d0a2.css" /><link data-color-theme="dark_tritanopia" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_tritanopia-a6f60cea68c08405.css" /><link data-color-theme="dark_tritanopia_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_tritanopia_high_contrast-f66faf28b2ea18b6.css" /><link data-color-theme="dark_dimmed" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_dimmed-6701f6218c53cf5b.css" /><link data-color-theme="dark_dimmed_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_dimmed_high_contrast-7037fa46ae124d97.css" />

  <style type="text/css">
    :root {
      --tab-size-preference: 4;
    }

    pre, code {
      tab-size: var(--tab-size-preference);
    }
  </style>

    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-primitives-97df7784617ce1ea.css" />
    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-9be9fe6313f476af.css" />
    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/global-62747e27e61258dc.css" />
    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/github-b04ca6fccda778e2.css" />
  <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/repository-72bd7d974b5ac1cc.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/code-4c5c0895f723f870.css" />

  

  <script type="application/json" id="client-env">{"locale":"en","featureFlags":["actions_caches_react_shell","actions_enable_background_steps","actions_new_hosted_runner_image_select_sizes_and_versions","actions_runners_react_shell","agent_author_search_expansion","agent_author_search_expansion_ui_pulls","alternate_user_config_repo","async_conversion_coverage_enabled","billing_billable_licenses_cost_center_bucket_fix","billing_budget_expiration","billing_cost_center_list_assigned_resources","billing_discount_threshold_notification","code_quality_enablement_banner_targeting","code_quality_remove_preview","code_view_raf_sticky_lines","codespaces_prebuild_region_target_update","coding_agent_third_party_model_ui","copilot_agent_snippy","copilot_ahp_tool_call_timing","copilot_api_agentic_issue_marshal_yaml","copilot_automation_repo_mcp_servers","copilot_automations_pagination","copilot_base_model_policy_row","copilot_chat_auto_mode_v2","copilot_chat_clear_model_selection_for_default_change","copilot_chat_early_task_provisioning","copilot_chat_persist_session_drafts","copilot_chat_vision_dotcom_chat_ga_gate","copilot_css_textarea_autosize","copilot_custom_copilots","copilot_custom_copilots_feature_preview","copilot_duplicate_thread","copilot_extensions_removal_on_marketplace","copilot_fix_failed_workflows_all_skus","copilot_hide_hovercard","copilot_immersive_task_hyperlinking","copilot_mc_cli_resume_any_users_task","copilot_mission_control_agent_merge_fix_ci","copilot_mission_control_agent_merge_resolve_conflicts","copilot_mission_control_awps_batching","copilot_mission_control_early_stop","copilot_mission_control_managed_sandbox_environments","copilot_mission_control_needs_attention","copilot_mission_control_reasoning_effort","copilot_mission_control_sandbox_remote_bypass","copilot_mission_control_task_alive_updates","copilot_mission_control_task_sharing","copilot_org_policy_page_focus_mode","copilot_share_active_subthread","copilot_spaces_ga","copilot_spaces_individual_policies_ga","copilot_swe_agent_authorization_status_ui","copilot_swe_agent_automation_resource_scoped_writes","copilot_swe_agent_discussion_comment_trigger","copilot_swe_agent_discussion_opened_trigger","copilot_swe_agent_discussion_updated_trigger","copilot_swe_agent_hide_model_picker_if_only_auto","copilot_swe_agent_issue_assigned_trigger","copilot_swe_agent_issue_comment_trigger","copilot_swe_agent_issue_labeled_trigger","copilot_swe_agent_pr_comment_model_picker","copilot_swe_agent_pull_request_assigned_trigger","copilot_swe_agent_pull_request_comment_trigger","copilot_swe_agent_pull_request_labeled_trigger","copilot_swe_agent_pull_request_merged_trigger","copilot_swe_agent_pull_request_opened_trigger","copilot_swe_agent_pull_request_ready_for_review_trigger","copilot_swe_agent_pull_request_review_requested_trigger","copilot_swe_agent_pull_request_review_submitted_trigger","copilot_swe_agent_pull_request_synchronize_trigger","copilot_swe_agent_sub_issue_added_trigger","copilot_swe_agent_use_subagents","copilot_task_api_github_rest_style","copilot_task_scoped_alive_channel","copilot_token_based_billing","copilot_unconfigured_is_inherited","copilot_user_can_upgrade_plan_field","copilot_web_integration_cutover","copilot_workbench_sunset_redirect","dashboard_agents_module_auth_token_check","dashboard_indexeddb_caching","fgpat_permissions_selector_redesign","glc_code_quality_repo_settings_workflow_config","hyperspace_2025_logged_out_batch_1","hyperspace_2025_logged_out_batch_2","hyperspace_2025_logged_out_batch_3","in_product_messaging_datadog_monitoring","ipm_ubb_individual_budget_banner","issue_fields_multi_select","issue_inline_avatars","issue_pinned_views","issue_pinned_views_team_vs_personal","issue_relative_time_micro","issue_viewer_paved_path","issues_expanded_file_types","issues_hide_closed_sub_issues","issues_lazy_load_comment_box_suggestions","issues_react_chrome_container_query_fix","labels_archiving","labels_archiving_info","landing_pages_ninetailed","lifecycle_label_name_updates","marketing_cookie_consent_banner","marketing_pages_search_explore_provider","memex_default_issue_create_repository","memex_live_update_hovercard","memex_mwl_filter_field_delimiter","memex_remove_deprecated_type_issue","merge_queue_restricted_pushers_warning","merge_status_header_feedback","milestone_closed_issues_prioritization","octocaptcha_origin_optimization","primer_react_css_anchor_positioning","primer_react_merged_forwarded_refs","primer_react_timeline_list_semantics","prs_copilot_app_open_action","prs_css_anchor_positioning","pull_request_copilot_attribution_header","pull_request_overview_merge_control","pull_request_overview_panel_edit_description","pull_request_persister","pull_request_stacks_navigation_shortcuts","pull_request_virtualization_image_estimate","pull_request_virtualization_loader_batching","pull_request_virtualization_scroll_compensation","pull_request_virtualization_scroll_intent","quick_search_lazy_suggestions","react_blob_isolate_code_lines","react_blob_ssr_content_visibility","react_data_router_tanstack_allowed","react_logged_out_repository_header","react_query_props_with_key","react_sandbox_future_tanstack","repo_app_turbo","repo_issues_sidebar_layout","repo_pulls_dashboard_declutter","repo_pulls_dashboard_ga","repo_pulls_dashboard_persistence","repos_contributors_limited_default_range","review_involves_filter","rule_ignored_file_paths","rulesets_actor_list_editor","sample_network_conn_type","security_center_artifact_filters_popover","see_who_reacted","semantic_similarity_duplicate_issue_detection","session_logs_ungroup_reasoning_text","set_sha256_on_repo_creation_form","site_banner_desktop_copilot_app","site_ghca_pixel_mona","site_github_app_ga_page","site_github_app_ga_page_highlight","site_github_app_mobile_native_share","site_global_banner_dev_days_attendee","site_global_nav_spark_models_removed","speculation_rules_ui_service","suggest_custom_property_values_copilot","suppress_automated_browser_vitals","swp_forms_disable_octocaptcha","thread_resolution_reason","update_issue_suggestions","viewscreen_sandbox","warn_inaccessible_attachments","webp_support","workstream_plugin_bootstrap"],"githubDomain":"https://github.com","copilotApiOverrideUrl":"https://api.githubcopilot.com","cmcApiUrl":"https://api.github.com/cmc_internal/api"}</script>
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/high-contrast-cookie-3663bcaacc724f4c.js"></script>
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/wp-runtime-721126455a2225e3.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/app-foundation-156c6259e31cc551.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/app-runtime-f6ce38f47c2e1d56.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/fetch-utilities-804a14996977c014.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ser-fb5d13278eb42203.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/tp-ea613009a991e211.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/environment-107a7753389a8a2d.js" defer="defer"></script>
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/app-runtime.25915bc98fb322a6.module.css" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/catalyst-52ed81112a548e10.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/selector-observer-e8810f64c443fb9b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/relative-time-element-fe7e72f699fdf493.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/by-9da36843ba9d191d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ja9-9a1160b939f2cd52.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/3h-55903cf2303047ad.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hk-0d35a1220587d888.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/jz5-c964b1a3671f2a92.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hj-1d800d09e9a8720a.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j0-1ad12374da9777f2.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/github-elements-531d35538b61fd0d.js" defer="defer"></script>
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/element-registry-bf5e3b2aee197122.js" defer="defer"></script>
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/runtime-helpers-5e0b3ae3c4036207.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/aria-live-752acdc868e2da64.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hotkey-e87ffadced20a3c9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-core-75bc55d9971828b7.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/a9-34620c7b13885011.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ur-643d2814115561a9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/4t6-5d0869970ac0aac0.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/pb0-a5c5ec36d311aeef.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/6n-afcf86ccabc4cad2.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/zj-f08c728cf00018aa.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/o6-2a1c68d269710ee9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/h9a-c6405aa090de0e84.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/vy6-3c3e6e96629c2ce4.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/js-4eb97d5803e657c0.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/g7-baf9e817ae102b01.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/unc-96389cade7bad821.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/nu-65322a6997c6c93c.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/behaviors-5dd3809b5c8bac3c.js" defer="defer"></script>
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/react-core.3792087592bf207a.module.css" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/code-menu-4318f0f4c608f3dd.js" defer="defer"></script>
  
  <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/primer-react-7afef75d393cf294.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/op-acddf38478d45ef9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ncx-461e4b09f2e67ee5.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/qmp-c7cfba40cf5a93b0.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j6-148a74299e5a01ab.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/t7l-a52ba56147f77909.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/4u-ec4874f70bfd5d76.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/s0-481bd34f90bc2bd7.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/y5-ed17e73b4c0bd15e.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/n4-be595475cdbf7d4b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j8-23a3c5ff8eef412d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/la-27679061f16e1495.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/iu-9806a0291a782cbe.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ftx-39fb490e3c1d778f.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/zi-32a0c3c081ea5cce.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/sg-7a5d50475874c0e1.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/pd-6a8710840033e042.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/86g-ec28c25ed7d5de06.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/sn-1bab7384818953b7.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/iq-6d4ecf6d2fb6993c.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/p2-7d8e7cee5b46cb45.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/7d-2e3cc25d719f3a95.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/4d-76d8acdf21a33266.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/tsb-e0f6288ab985d9d2.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/lf-910ef220ce85c660.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/2j-2f19c1afd2ceaf93.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/me-f1476ec44a29f34a.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/p2u-e654a57b1a70c47d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/5d-d97cc006d4da4d9b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/r5-38f013bc2c0fd298.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/r6s-9039f5619230a653.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/9e-cece06724bf6ea3b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/x9-3e077a3a37a73f9f.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/pj-87629cb5389d7663.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/eq-3764fd5f66494289.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/13-d889936dff7e5c0f.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/44-8193eea4af825ead.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/v4-9c1327d212e52a0d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/id-7f39706ba9007db6.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ah-271362a1ed227d03.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/s1g-d434d712bca59d3a.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/vz-d7f4a583896f872e.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/47-c8c0ce2700acc5be.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/code-view-4118a687d0150749.js" defer="defer"></script>
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.2d881b4d4a503d1c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/pj.75627bfeb9ceb1da.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/ah.2623f7c6ecbe2ecd.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/47.78770c57a48a810c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/code-view.37656c95a9729fb9.module.css" />


  <title>nova-studio/BUG_ANALYSIS.md at main · fuxingliang/nova-studio · GitHub</title>



  <meta name="route-pattern" content="/:user_id/:repository/blob/*name(/*path)" data-turbo-transient>
  <meta name="route-controller" content="blob" data-turbo-transient>
  <meta name="route-action" content="show" data-turbo-transient>
  <meta name="fetch-nonce" content="v2:8ba60f1f-e228-d449-0696-af290d76da99">

    
  <meta name="current-catalog-service-hash" content="f3abb0cc802f3d7b95fc8762b94bdcb13bf39634c40c357301c4aa1d67a256fb">


  <meta name="request-id" content="8E10:9870E:AE6090B:E348D90:6ACA63F3" data-pjax-transient="true"/><meta name="html-safe-nonce" content="08d81a0751d821dfcb45a173e7a8993f0c76b95caac144751e5a081250d357f6" data-pjax-transient="true"/><meta name="visitor-payload" content="eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4RTEwOjk4NzBFOkFFNjA5MEI6RTM0OEQ5MDo2QUNBNjNGMyIsInZpc2l0b3JfaWQiOiI3OTE4OTE3Njg4MzM1NDI2NTQ3IiwicmVnaW9uX2VkZ2UiOiJmcmEiLCJyZWdpb25fcmVuZGVyIjoiZnJhIn0=" data-pjax-transient="true"/><meta name="visitor-hmac" content="6f562142638467048ea6e43a8ab924a0bcf5d051f8eb9aa284c6ee777459fa86" data-pjax-transient="true"/>


    <meta name="hovercard-subject-tag" content="repository:1327765093" data-turbo-transient>


  <meta name="github-keyboard-shortcuts" content="repository,source-code,file-tree,copilot" data-turbo-transient="true" />
  

  <meta name="selected-link" value="repo_source" data-turbo-transient>
  <link rel="assets" href="https://github.githubassets.com/">

    <meta name="google-site-verification" content="Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I">

<meta name="octolytics-url" content="https://collector.github.com/github/collect" />





  <meta name="analytics-location" content="/&lt;user-name&gt;/&lt;repo-name&gt;/blob/show" data-turbo-transient="true" />

  




    <meta name="user-login" content="">

  

    <meta name="viewport" content="width=device-width">

    

      <meta name="description" content="Nova Studio - Windows desktop workbench for local LLM inference (vLLM / SGLang / llama.cpp via WSL2), bridging WSL engines to any OpenAI-compatible client - nova-studio/BUG_ANALYSIS.md at main · fuxingliang/nova-studio">

      <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub">

    <link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub">
    <meta property="fb:app_id" content="1401488693436528">
    <meta name="apple-itunes-app" content="app-id=1477376905, app-argument=https://github.com/fuxingliang/nova-studio/blob/main/BUG_ANALYSIS.md" />

      <meta name="twitter:image" content="https://opengraph.githubassets.com/41eca8d499cea705632bd6eefa456e8c02d277b9ae735a659afbcb358514f7cb/fuxingliang/nova-studio" /><meta name="twitter:site" content="@github" /><meta name="twitter:card" content="summary_large_image" /><meta name="twitter:title" content="nova-studio/BUG_ANALYSIS.md at main · fuxingliang/nova-studio" /><meta name="twitter:description" content="Nova Studio - Windows desktop workbench for local LLM inference (vLLM / SGLang / llama.cpp via WSL2), bridging WSL engines to any OpenAI-compatible client - fuxingliang/nova-studio" />
  <meta property="og:image" content="https://opengraph.githubassets.com/41eca8d499cea705632bd6eefa456e8c02d277b9ae735a659afbcb358514f7cb/fuxingliang/nova-studio" /><meta property="og:image:alt" content="Nova Studio - Windows desktop workbench for local LLM inference (vLLM / SGLang / llama.cpp via WSL2), bridging WSL engines to any OpenAI-compatible client - fuxingliang/nova-studio" /><meta property="og:image:width" content="1200" /><meta property="og:image:height" content="600" /><meta property="og:site_name" content="GitHub" /><meta property="og:type" content="object" /><meta property="og:title" content="nova-studio/BUG_ANALYSIS.md at main · fuxingliang/nova-studio" /><meta property="og:url" content="https://github.com/fuxingliang/nova-studio/blob/main/BUG_ANALYSIS.md" /><meta property="og:description" content="Nova Studio - Windows desktop workbench for local LLM inference (vLLM / SGLang / llama.cpp via WSL2), bridging WSL engines to any OpenAI-compatible client - fuxingliang/nova-studio" />
  




      <meta name="hostname" content="github.com">



        <meta name="expected-hostname" content="github.com">


  <meta http-equiv="x-pjax-version" content="d05be8f8b6905b6460fc264e80447721dfee1e32cf9e4291c4bf58f160c9f705" data-turbo-track="reload">
  <meta http-equiv="x-pjax-csp-version" content="c4a65e47b0c850e1157ae8e66298070851d7e3b558038de5a3b4ff7a93e630ed" data-turbo-track="reload">
  <meta http-equiv="x-pjax-css-version" content="a80b0545b169f440b929ce2b977c76b6988f014cca6513fb83c5df6581635fb3" data-turbo-track="reload">
  <meta http-equiv="x-pjax-js-version" content="af51c6f9d659be0324665373df3ee542f817dbd7f66f352a087935f2ceabe545" data-turbo-track="reload">

  <meta name="turbo-cache-control" content="no-preview" data-turbo-transient="">

      <meta name="turbo-cache-control" content="no-cache" data-turbo-transient>

    <meta data-hydrostats="publish">

  <meta name="go-import" content="github.com/fuxingliang/nova-studio git https://github.com/fuxingliang/nova-studio.git">

  <meta name="octolytics-dimension-user_id" content="37263150" /><meta name="octolytics-dimension-user_login" content="fuxingliang" /><meta name="octolytics-dimension-repository_id" content="1327765093" /><meta name="octolytics-dimension-repository_nwo" content="fuxingliang/nova-studio" /><meta name="octolytics-dimension-repository_public" content="true" /><meta name="octolytics-dimension-repository_is_fork" content="false" /><meta name="octolytics-dimension-repository_network_root_id" content="1327765093" /><meta name="octolytics-dimension-repository_network_root_nwo" content="fuxingliang/nova-studio" />
  



    

    <meta name="turbo-body-classes" content="logged-out env-production page-responsive">
  <meta name="disable-turbo" content="false">


  <meta name="browser-stats-url" content="https://api.github.com/_private/browser/stats">


  <meta name="browser-errors-url" content="https://api.github.com/_private/browser/errors">

  <meta name="release" content="3b1bb5b10f5c7fd1769d56e38b15dfddb34052a8" data-turbo-track="reload">
  <meta name="ui-target" content="full">

  <link rel="mask-icon" href="https://github.githubassets.com/assets/pinned-octocat-093da3e6fa40.svg" color="#000000">
  <link rel="alternate icon" class="js-site-favicon" type="image/png" href="https://github.githubassets.com/favicons/favicon.png">
  <link rel="icon" class="js-site-favicon" type="image/svg+xml" href="https://github.githubassets.com/favicons/favicon.svg" data-base-href="https://github.githubassets.com/favicons/favicon">

<meta name="theme-color" content="#1e2327">
<meta name="color-scheme" content="light dark" />


  <link rel="manifest" href="/manifest.json" crossOrigin="use-credentials">

  </head>

  <body class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
    <div data-turbo-body class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
      <div id="__primerPortalRoot__" style="z-index: 1000; position: absolute; width: 100%;" data-turbo-permanent></div>
      

    <div class="position-relative header-wrapper js-header-wrapper ">
      <a href="#start-of-content" data-skip-target-assigned="false" class="px-2 tmp-py-4 color-bg-accent-emphasis color-fg-on-emphasis show-on-focus js-skip-to-content">Skip to content</a>

      <span data-view-component="true" class="progress-pjax-loader Progress position-fixed width-full">
    <span style="width: 0%;" data-view-component="true" class="Progress-item progress-pjax-loader-bar left-0 top-0 color-bg-accent-emphasis"></span>
</span>      
      <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/19-c660652a0a1639be.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/keyboard-shortcuts-dialog-47c5223d8d1af8ef.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.2d881b4d4a503d1c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/keyboard-shortcuts-dialog.d53d993320d57e14.module.css" />

<react-partial
  partial-name="keyboard-shortcuts-dialog"
  data-ssr="false"
  data-attempted-ssr="false"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-partial.embeddedData">{"props":{"docsUrl":"https://docs.github.com/get-started/accessibility/keyboard-shortcuts"}}</script>
  <div data-target="react-partial.reactRoot"></div>
</react-partial>





      

          <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/app-install-banner-partial-3c87deb7f0f20434.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.2d881b4d4a503d1c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/app-install-banner-partial.7b357012e82003e7.module.css" />

<react-partial
  partial-name="app-install-banner-partial"
  data-ssr="false"
  data-attempted-ssr="false"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-partial.embeddedData">{"props":{}}</script>
  <div data-target="react-partial.reactRoot"></div>
</react-partial>


          

                <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/et9-7eeec247c287fca4.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/94v-e20946127faa8f6e.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/fz5-892a9e99cc92858d.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/jag-441e702bfd4c7904.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hw-8ce7888b57d0a23c.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/rq-0ec82a12cf538a4d.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/1m-a7a4c022483b2713.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/marketing-header-70703fe17422eb58.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.2d881b4d4a503d1c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-brand-css.fbc35b3d20e988ff.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/1m.fec8b575d0e5234f.module.css" />

<react-partial
  partial-name="marketing-header"
  data-ssr="true"
  data-attempted-ssr="true"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-partial.embeddedData">{"props":{"color_mode":"dark","logged_in":false,"marketing_page":false,"home_path":"/","login_path":"/login?return_to=https%3A%2F%2Fgithub.com%2Ffuxingliang%2Fnova-studio%2Fblob%2Fmain%2FBUG_ANALYSIS.md","signup_path":"/signup?ref_cta=Sign+up\u0026ref_loc=header+logged+out\u0026ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fblob%2Fshow\u0026source=header-repo\u0026source_repo=fuxingliang%2Fnova-studio","signup_enabled":true,"is_signup_controller":false,"show_search_and_nav":true,"hide_search":false,"private_mode_enabled":false,"should_use_dotcom_links":true,"auth_hydro_click":"{\"event_type\":\"authentication.click\",\"payload\":{\"location_in_page\":\"site header menu\",\"repository_id\":null,\"auth_type\":\"SIGN_UP\",\"originating_url\":\"https://github.com/fuxingliang/nova-studio/blob/main/BUG_ANALYSIS.md\",\"user_id\":null}}","auth_hydro_click_hmac":"137fe32c5de8902b0575bdec28334d124cde87c0862345c03da61fcc14506c16","overlay":false,"fixed":false}}</script>
  <div data-target="react-partial.reactRoot"><div data-color-mode="dark" data-light-theme="light" data-dark-theme="dark"><header class="MarketingHeader-module__root__Tk7n3 HeaderMktg header-logged-out" role="banner" data-marketing-header="true" data-color-mode="dark" data-light-theme="light" data-dark-theme="dark" data-is-top="true"><h2 class="MarketingHeader-module__visuallyHidden__sqKsl">Navigation Menu</h2><button type="button" class="MarketingHeader-module__backdrop__sw4RU" aria-label="Close navigation menu"></button><div class="MarketingHeader-module__bar__mBSyE"><div class="MarketingHeader-module__topRow__yeury"><div class="MarketingHeader-module__toggleSlot__hDxbh"><button type="button" class="HeaderMenuToggle-module__toggle__i8EiC" aria-label="Toggle navigation" aria-expanded="false"><span class="HeaderMenuToggle-module__toggleBar__jVN0H"></span><span class="HeaderMenuToggle-module__toggleBar__jVN0H"></span><span class="HeaderMenuToggle-module__toggleBar__jVN0H"></span></button></div><a href="/" aria-label="Homepage" class="HeaderLogo-module__logo__UFyHI" data-analytics-event="{&quot;action&quot;:&quot;homepage&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;logo&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;homepage_link_logo_header&quot;}"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-mark-github" viewBox="0 0 24 24" width="32" height="32" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.226 17.284c-2.965-.36-5.054-2.493-5.054-5.256 0-1.123.404-2.336 1.078-3.144-.292-.741-.247-2.314.09-2.965.898-.112 2.111.36 2.83 1.01.853-.269 1.752-.404 2.853-.404 1.1 0 1.999.135 2.807.382.696-.629 1.932-1.1 2.83-.988.315.606.36 2.179.067 2.942.72.854 1.101 2 1.101 3.167 0 2.763-2.089 4.852-5.098 5.234.763.494 1.28 1.572 1.28 2.807v2.336c0 .674.561 1.056 1.235.786 4.066-1.55 7.255-5.615 7.255-10.646C23.5 6.188 18.334 1 11.978 1 5.62 1 .5 6.188.5 12.545c0 4.986 3.167 9.12 7.435 10.669.606.225 1.19-.18 1.19-.786V20.63a2.9 2.9 0 0 1-1.078.224c-1.483 0-2.359-.808-2.987-2.313-.247-.607-.517-.966-1.034-1.033-.27-.023-.359-.135-.359-.27 0-.27.45-.471.898-.471.652 0 1.213.404 1.797 1.235.45.651.921.943 1.483.943.561 0 .92-.202 1.437-.719.382-.381.674-.718.944-.943"></path></svg></a><div class="AuthCTAs-module__mobileActions__NNzeV"><a class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw AuthCTAs-module__cta__WpwQq" href="/login?return_to=https%3A%2F%2Fgithub.com%2Ffuxingliang%2Fnova-studio%2Fblob%2Fmain%2FBUG_ANALYSIS.md" data-analytics-event="{&quot;action&quot;:&quot;sign_in&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;auth_cta&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;sign_in_link_auth_cta_header&quot;}" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/fuxingliang/nova-studio/blob/main/BUG_ANALYSIS.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="137fe32c5de8902b0575bdec28334d124cde87c0862345c03da61fcc14506c16"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH">Sign in</span></span></a><button class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw HeaderAppearanceSettings-module__trigger__hUheK" type="button" aria-haspopup="dialog" aria-labelledby="_R_3dd_"><span class="Primer_Brand__Button-module__Button__leading-visual___jjtTe" data-testid="Button-leading-visual"><svg data-component="Octicon" focusable="false" aria-hidden="true" class="octicon octicon-sliders Primer_Brand__Button-module__Button__icon-visual____qybb" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M15 2.75a.75.75 0 0 1-.75.75h-4a.75.75 0 0 1 0-1.5h4a.75.75 0 0 1 .75.75Zm-8.5.75v1.25a.75.75 0 0 0 1.5 0v-4a.75.75 0 0 0-1.5 0V2H1.75a.75.75 0 0 0 0 1.5H6.5Zm1.25 5.25a.75.75 0 0 0 0-1.5h-6a.75.75 0 0 0 0 1.5h6ZM15 8a.75.75 0 0 1-.75.75H11.5V10a.75.75 0 1 1-1.5 0V6a.75.75 0 0 1 1.5 0v1.25h2.75A.75.75 0 0 1 15 8Zm-9 5.25v-2a.75.75 0 0 0-1.5 0v1.25H1.75a.75.75 0 0 0 0 1.5H4.5v1.25a.75.75 0 0 0 1.5 0v-2Zm9 0a.75.75 0 0 1-.75.75h-6a.75.75 0 0 1 0-1.5h6a.75.75 0 0 1 .75.75Z"></path></svg></span><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH"></span></span></button><div class="Primer_Brand__Tooltip-module__Tooltip___0Eipx" data-direction="s" aria-hidden="true" id="_R_3dd_">Appearance settings</div></div></div><div class="MarketingHeader-module__menu__GIy3y"><div class="MarketingHeader-module__menuWrapper__owstH"><nav class="MarketingNavigation-module__nav__W0KYY" aria-label="Global"><ul class="MarketingNavigation-module__list__tFbMb"><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_nd_">Platform<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_nd_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5knd_">AI CODE CREATION</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5knd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/copilot" data-analytics-event="{&quot;action&quot;:&quot;github_copilot&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_copilot_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copilot NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.998 15.035c-4.562 0-7.873-2.914-7.998-3.749V9.338c.085-.628.677-1.686 1.588-2.065.013-.07.024-.143.036-.218.029-.183.06-.384.126-.612-.201-.508-.254-1.084-.254-1.656 0-.87.128-1.769.693-2.484.579-.733 1.494-1.124 2.724-1.261 1.206-.134 2.262.034 2.944.765.05.053.096.108.139.165.044-.057.094-.112.143-.165.682-.731 1.738-.899 2.944-.765 1.23.137 2.145.528 2.724 1.261.566.715.693 1.614.693 2.484 0 .572-.053 1.148-.254 1.656.066.228.098.429.126.612.012.076.024.148.037.218.924.385 1.522 1.471 1.591 2.095v1.872c0 .766-3.351 3.795-8.002 3.795Zm0-1.485c2.28 0 4.584-1.11 5.002-1.433V7.862l-.023-.116c-.49.21-1.075.291-1.727.291-1.146 0-2.059-.327-2.71-.991A3.222 3.222 0 0 1 8 6.303a3.24 3.24 0 0 1-.544.743c-.65.664-1.563.991-2.71.991-.652 0-1.236-.081-1.727-.291l-.023.116v4.255c.419.323 2.722 1.433 5.002 1.433ZM6.762 2.83c-.193-.206-.637-.413-1.682-.297-1.019.113-1.479.404-1.713.7-.247.312-.369.789-.369 1.554 0 .793.129 1.171.308 1.371.162.181.519.379 1.442.379.853 0 1.339-.235 1.638-.54.315-.322.527-.827.617-1.553.117-.935-.037-1.395-.241-1.614Zm4.155-.297c-1.044-.116-1.488.091-1.681.297-.204.219-.359.679-.242 1.614.091.726.303 1.231.618 1.553.299.305.784.54 1.638.54.922 0 1.28-.198 1.442-.379.179-.2.308-.578.308-1.371 0-.765-.123-1.242-.37-1.554-.233-.296-.693-.587-1.713-.7Z"></path><path d="M6.25 9.037a.75.75 0 0 1 .75.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 .75-.75Zm4.25.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 1.5 0Z"></path></svg>GitHub Copilot</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Write better code with AI</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/ai/github-app" data-analytics-event="{&quot;action&quot;:&quot;github_copilot_app&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_copilot_app_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-mark-github NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.766 11.328c-2.063-.25-3.516-1.734-3.516-3.656 0-.781.281-1.625.75-2.188-.203-.515-.172-1.609.063-2.062.625-.078 1.468.25 1.968.703.594-.187 1.219-.281 1.985-.281.765 0 1.39.094 1.953.265.484-.437 1.344-.765 1.969-.687.218.422.25 1.515.046 2.047.5.593.766 1.39.766 2.203 0 1.922-1.453 3.375-3.547 3.64.531.344.89 1.094.89 1.954v1.625c0 .468.391.734.86.547C13.781 14.359 16 11.53 16 8.03 16 3.61 12.406 0 7.984 0 3.563 0 0 3.61 0 8.031a7.88 7.88 0 0 0 5.172 7.422c.422.156.828-.125.828-.547v-1.25c-.219.094-.5.156-.75.156-1.031 0-1.64-.562-2.078-1.609-.172-.422-.36-.672-.719-.719-.187-.015-.25-.093-.25-.187 0-.188.313-.328.625-.328.453 0 .844.281 1.25.86.313.452.64.655 1.031.655s.641-.14 1-.5c.266-.265.47-.5.657-.656"></path></svg>GitHub Copilot app</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Direct agents from issue to merge</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/mcp" data-analytics-event="{&quot;action&quot;:&quot;mcp_registry&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;mcp_registry_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-mcp NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M5.52 1.12a3.578 3.578 0 0 1 6.078 2.98 3.578 3.578 0 0 1 2.982 6.08l-3.292 3.293a.252.252 0 0 0 0 .354l.843.843a.749.749 0 1 1-1.06 1.06l-.844-.843a1.75 1.75 0 0 1 0-2.474L13.52 9.12a2.08 2.08 0 0 0 0-2.94 2.08 2.08 0 0 0-2.94 0L7.731 9.03A.75.75 0 0 1 6.67 7.97l2.85-2.85a2.08 2.08 0 0 0 0-2.94 2.08 2.08 0 0 0-2.94 0l-4.799 4.8A.75.75 0 0 1 .72 5.92Z"></path><path d="M7.52 3.12a.749.749 0 1 1 1.06 1.06L5.731 7.03A2.079 2.079 0 0 0 8.67 9.97l2.85-2.85a.749.749 0 1 1 1.06 1.06l-2.849 2.85A3.578 3.578 0 0 1 4.67 5.97Z"></path></svg>MCP Registry</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Integrate external tools</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9knd_">DEVELOPER WORKFLOWS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9knd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/actions" data-analytics-event="{&quot;action&quot;:&quot;actions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;actions_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-workflow NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 1.75C0 .784.784 0 1.75 0h3.5C6.216 0 7 .784 7 1.75v3.5A1.75 1.75 0 0 1 5.25 7H4v4a1 1 0 0 0 1 1h4v-1.25C9 9.784 9.784 9 10.75 9h3.5c.966 0 1.75.784 1.75 1.75v3.5A1.75 1.75 0 0 1 14.25 16h-3.5A1.75 1.75 0 0 1 9 14.25v-.75H5A2.5 2.5 0 0 1 2.5 11V7h-.75A1.75 1.75 0 0 1 0 5.25Zm1.75-.25a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Zm9 9a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Z"></path></svg>Actions</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Automate any workflow</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/codespaces" data-analytics-event="{&quot;action&quot;:&quot;codespaces&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;codespaces_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-codespaces NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 11.25c0-.966.784-1.75 1.75-1.75h12.5c.966 0 1.75.784 1.75 1.75v3A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25Zm2-9.5C2 .784 2.784 0 3.75 0h8.5C13.216 0 14 .784 14 1.75v5a1.75 1.75 0 0 1-1.75 1.75h-8.5A1.75 1.75 0 0 1 2 6.75Zm1.75-.25a.25.25 0 0 0-.25.25v5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-5a.25.25 0 0 0-.25-.25Zm-2 9.5a.25.25 0 0 0-.25.25v3c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-3a.25.25 0 0 0-.25-.25Z"></path><path d="M7 12.75a.75.75 0 0 1 .75-.75h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1-.75-.75Zm-4 0a.75.75 0 0 1 .75-.75h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1-.75-.75Z"></path></svg>Codespaces</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Instant dev environments</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/issues" data-analytics-event="{&quot;action&quot;:&quot;issues&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;issues_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-issue-opened NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"></path></svg>Issues</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Plan and track work</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/code-review" data-analytics-event="{&quot;action&quot;:&quot;code_review&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;code_review_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-code NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path></svg>Code Review</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Manage code changes</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/code-quality" data-analytics-event="{&quot;action&quot;:&quot;code_quality&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;code_quality_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-codescan-checkmark NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.28 6.28a.75.75 0 1 0-1.06-1.06L6.25 8.19l-.97-.97a.75.75 0 0 0-1.06 1.06l1.5 1.5a.75.75 0 0 0 1.06 0l3.5-3.5Z"></path><path d="M7.5 15a7.5 7.5 0 1 1 5.807-2.754l2.473 2.474a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215l-2.474-2.473A7.472 7.472 0 0 1 7.5 15Zm0-13.5a6 6 0 1 0 4.094 10.386.748.748 0 0 1 .293-.292 6.002 6.002 0 0 0 1.117-6.486A6.002 6.002 0 0 0 7.5 1.5Z"></path></svg>Code Quality</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enforce quality at merge</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dknd_">APPLICATION SECURITY</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dknd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security" data-analytics-event="{&quot;action&quot;:&quot;github_advanced_security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_advanced_security_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-shield-check NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m8.533.133 5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667l5.25-1.68a1.748 1.748 0 0 1 1.066 0Zm-.61 1.429.001.001-5.25 1.68a.251.251 0 0 0-.174.237V7c0 1.36.275 2.666 1.057 3.859.784 1.194 2.121 2.342 4.366 3.298a.196.196 0 0 0 .154 0c2.245-.957 3.582-2.103 4.366-3.297C13.225 9.666 13.5 8.358 13.5 7V3.48a.25.25 0 0 0-.174-.238l-5.25-1.68a.25.25 0 0 0-.153 0ZM11.28 6.28l-3.5 3.5a.75.75 0 0 1-1.06 0l-1.5-1.5a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l.97.97 2.97-2.97a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path></svg>GitHub Advanced Security</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Find and fix vulnerabilities</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security/code-security" data-analytics-event="{&quot;action&quot;:&quot;code_security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;code_security_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-code-square NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25Zm7.47 3.97a.75.75 0 0 1 1.06 0l2 2a.75.75 0 0 1 0 1.06l-2 2a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L10.69 8 9.22 6.53a.75.75 0 0 1 0-1.06ZM6.78 6.53 5.31 8l1.47 1.47a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215l-2-2a.75.75 0 0 1 0-1.06l2-2a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path></svg>Code security</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Secure your code as you build</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security/secret-protection" data-analytics-event="{&quot;action&quot;:&quot;secret_protection&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;secret_protection_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-lock NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M4 4a4 4 0 0 1 8 0v2h.25c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 12.25 15h-8.5A1.75 1.75 0 0 1 2 13.25v-5.5C2 6.784 2.784 6 3.75 6H4Zm8.25 3.5h-8.5a.25.25 0 0 0-.25.25v5.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25ZM10.5 6V4a2.5 2.5 0 1 0-5 0v2Z"></path></svg>Secret protection</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Stop leaks before they start</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ NavGroup-module__hasSeparator__FnMrN"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_hknd_">EXPLORE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_hknd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/why-github" data-analytics-event="{&quot;action&quot;:&quot;why_github&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;why_github_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Why GitHub</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://docs.github.com" data-analytics-event="{&quot;action&quot;:&quot;documentation&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;documentation_link_platform_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Documentation</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://github.blog" data-analytics-event="{&quot;action&quot;:&quot;blog&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;blog_link_platform_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Blog</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://github.blog/changelog" data-analytics-event="{&quot;action&quot;:&quot;changelog&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;changelog_link_platform_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Changelog</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/marketplace" data-analytics-event="{&quot;action&quot;:&quot;marketplace&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;marketplace_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Marketplace</span></a></li></ul></div></li></ul><div class="NavDropdown-module__trailingLinkContainer__VgJGL"><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/features" data-analytics-event="{&quot;action&quot;:&quot;view_all_features&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_features_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all features</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></div></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_17d_">Solutions<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_17d_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5l7d_">BY COMPANY SIZE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5l7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/enterprise" data-analytics-event="{&quot;action&quot;:&quot;enterprises&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;enterprises_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Enterprises</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/team" data-analytics-event="{&quot;action&quot;:&quot;small_and_medium_teams&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;small_and_medium_teams_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Small and medium teams</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/enterprise/startups" data-analytics-event="{&quot;action&quot;:&quot;startups&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;startups_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Startups</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/nonprofits" data-analytics-event="{&quot;action&quot;:&quot;nonprofits&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;nonprofits_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Nonprofits</span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9l7d_">BY USE CASE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9l7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/app-modernization" data-analytics-event="{&quot;action&quot;:&quot;app_modernization&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;app_modernization_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">App Modernization</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/devsecops" data-analytics-event="{&quot;action&quot;:&quot;devsecops&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;devsecops_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">DevSecOps</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/devops" data-analytics-event="{&quot;action&quot;:&quot;devops&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;devops_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">DevOps</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/ci-cd" data-analytics-event="{&quot;action&quot;:&quot;ci/cd&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;ci/cd_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">CI/CD</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/solutions/use-case" data-analytics-event="{&quot;action&quot;:&quot;view_all_use_cases&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_use_cases_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all use cases</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dl7d_">BY INDUSTRY</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dl7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/healthcare" data-analytics-event="{&quot;action&quot;:&quot;healthcare&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;healthcare_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Healthcare</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/financial-services" data-analytics-event="{&quot;action&quot;:&quot;financial_services&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;financial_services_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Financial services</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/manufacturing" data-analytics-event="{&quot;action&quot;:&quot;manufacturing&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;manufacturing_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Manufacturing</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/government" data-analytics-event="{&quot;action&quot;:&quot;government&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;government_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Government</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/solutions/industry" data-analytics-event="{&quot;action&quot;:&quot;view_all_industries&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_industries_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all industries</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></li></ul></div></li></ul><div class="NavDropdown-module__trailingLinkContainer__VgJGL"><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/solutions" data-analytics-event="{&quot;action&quot;:&quot;view_all_solutions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_solutions_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all solutions</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></div></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_1nd_">Resources<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_1nd_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5lnd_">EXPLORE BY TOPIC</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5lnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=ai" data-analytics-event="{&quot;action&quot;:&quot;ai&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;ai_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">AI</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=software-development" data-analytics-event="{&quot;action&quot;:&quot;software_development&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;software_development_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Software Development</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=devops" data-analytics-event="{&quot;action&quot;:&quot;devops&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;devops_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">DevOps</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=security" data-analytics-event="{&quot;action&quot;:&quot;security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;security_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Security</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/resources/articles" data-analytics-event="{&quot;action&quot;:&quot;view_all_topics&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_topics_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all topics</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9lnd_">EXPLORE BY TYPE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9lnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/customer-stories" data-analytics-event="{&quot;action&quot;:&quot;customer_stories&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;customer_stories_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Customer stories</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/events" data-analytics-event="{&quot;action&quot;:&quot;events__webinars&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;events__webinars_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Events &amp; webinars</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/whitepapers" data-analytics-event="{&quot;action&quot;:&quot;ebooks__reports&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;ebooks__reports_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Ebooks &amp; reports</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/executive-insights" data-analytics-event="{&quot;action&quot;:&quot;business_insights&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;business_insights_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Business insights</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://skills.github.com" data-analytics-event="{&quot;action&quot;:&quot;github_skills&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_skills_link_resources_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">GitHub Skills</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dlnd_">SUPPORT &amp; SERVICES</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dlnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://docs.github.com" data-analytics-event="{&quot;action&quot;:&quot;documentation&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;documentation_link_resources_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Documentation</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://support.github.com" data-analytics-event="{&quot;action&quot;:&quot;customer_support&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;customer_support_link_resources_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Customer support</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/orgs/community/discussions" data-analytics-event="{&quot;action&quot;:&quot;community_forum&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;community_forum_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Community forum</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/trust-center" data-analytics-event="{&quot;action&quot;:&quot;trust_center&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;trust_center_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Trust center</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/partners" data-analytics-event="{&quot;action&quot;:&quot;partners&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;partners_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Partners</span></a></li></ul></div></li></ul><div class="NavDropdown-module__trailingLinkContainer__VgJGL"><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/resources" data-analytics-event="{&quot;action&quot;:&quot;view_all_resources&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_resources_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all resources</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></div></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_27d_">Open Source<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_27d_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5m7d_">COMMUNITY</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5m7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/open-source/sponsors" data-analytics-event="{&quot;action&quot;:&quot;github_sponsors&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_sponsors_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-sponsor-tiers NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.586 1C12.268 1 13.5 2.37 13.5 4.25c0 1.745-.996 3.359-2.622 4.831-.166.15-.336.297-.509.438l1.116 5.584a.75.75 0 0 1-.991.852l-2.409-.876a.25.25 0 0 0-.17 0l-2.409.876a.75.75 0 0 1-.991-.852L5.63 9.519a13.78 13.78 0 0 1-.51-.438C3.497 7.609 2.5 5.995 2.5 4.25 2.5 2.37 3.732 1 5.414 1c.963 0 1.843.403 2.474 1.073L8 2.198l.112-.125a3.385 3.385 0 0 1 2.283-1.068L10.586 1Zm-3.621 9.495-.718 3.594 1.155-.42a1.75 1.75 0 0 1 1.028-.051l.168.051 1.154.42-.718-3.592c-.199.13-.37.235-.505.314l-.169.097a.75.75 0 0 1-.72 0 9.54 9.54 0 0 1-.515-.308l-.16-.105ZM10.586 2.5c-.863 0-1.611.58-1.866 1.459-.209.721-1.231.721-1.44 0C7.025 3.08 6.277 2.5 5.414 2.5 4.598 2.5 4 3.165 4 4.25c0 1.23.786 2.504 2.128 3.719.49.443 1.018.846 1.546 1.198l.325.21.076-.047.251-.163a13.341 13.341 0 0 0 1.546-1.198C11.214 6.754 12 5.479 12 4.25c0-1.085-.598-1.75-1.414-1.75Z"></path></svg>GitHub Sponsors</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Fund open source developers</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9m7d_">PROGRAMS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9m7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://securitylab.github.com" data-analytics-event="{&quot;action&quot;:&quot;security_lab&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;security_lab_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Security Lab</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://maintainers.github.com" data-analytics-event="{&quot;action&quot;:&quot;maintainer_community&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;maintainer_community_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Maintainer Community</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://stars.github.com" data-analytics-event="{&quot;action&quot;:&quot;github_stars&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_stars_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">GitHub Stars</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://archiveprogram.github.com" data-analytics-event="{&quot;action&quot;:&quot;archive_program&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;archive_program_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Archive Program</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dm7d_">REPOSITORIES</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dm7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/topics" data-analytics-event="{&quot;action&quot;:&quot;topics&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;topics_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Topics</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/trending" data-analytics-event="{&quot;action&quot;:&quot;trending&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;trending_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Trending</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/collections" data-analytics-event="{&quot;action&quot;:&quot;collections&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;collections_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Collections</span></a></li></ul></div></li></ul></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_2nd_">Enterprise<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_2nd_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5mnd_">ENTERPRISE SOLUTIONS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5mnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/enterprise" data-analytics-event="{&quot;action&quot;:&quot;enterprise_platform&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;enterprise_platform_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-stack NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.122.392a1.75 1.75 0 0 1 1.756 0l5.003 2.902c.83.481.83 1.68 0 2.162L8.878 8.358a1.75 1.75 0 0 1-1.756 0L2.119 5.456a1.251 1.251 0 0 1 0-2.162ZM8.125 1.69a.248.248 0 0 0-.25 0l-4.63 2.685 4.63 2.685a.248.248 0 0 0 .25 0l4.63-2.685ZM1.601 7.789a.75.75 0 0 1 1.025-.273l5.249 3.044a.248.248 0 0 0 .25 0l5.249-3.044a.75.75 0 0 1 .752 1.298l-5.248 3.044a1.75 1.75 0 0 1-1.756 0L1.874 8.814A.75.75 0 0 1 1.6 7.789Zm0 3.5a.75.75 0 0 1 1.025-.273l5.249 3.044a.248.248 0 0 0 .25 0l5.249-3.044a.75.75 0 0 1 .752 1.298l-5.248 3.044a1.75 1.75 0 0 1-1.756 0l-5.248-3.044a.75.75 0 0 1-.273-1.025Z"></path></svg>Enterprise platform</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">AI-powered developer platform</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9mnd_">AVAILABLE ADD-ONS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9mnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security" data-analytics-event="{&quot;action&quot;:&quot;github_advanced_security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_advanced_security_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-shield-check NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m8.533.133 5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667l5.25-1.68a1.748 1.748 0 0 1 1.066 0Zm-.61 1.429.001.001-5.25 1.68a.251.251 0 0 0-.174.237V7c0 1.36.275 2.666 1.057 3.859.784 1.194 2.121 2.342 4.366 3.298a.196.196 0 0 0 .154 0c2.245-.957 3.582-2.103 4.366-3.297C13.225 9.666 13.5 8.358 13.5 7V3.48a.25.25 0 0 0-.174-.238l-5.25-1.68a.25.25 0 0 0-.153 0ZM11.28 6.28l-3.5 3.5a.75.75 0 0 1-1.06 0l-1.5-1.5a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l.97.97 2.97-2.97a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path></svg>GitHub Advanced Security</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enterprise-grade security features</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/copilot/copilot-business" data-analytics-event="{&quot;action&quot;:&quot;copilot_for_business&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;copilot_for_business_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copilot NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.998 15.035c-4.562 0-7.873-2.914-7.998-3.749V9.338c.085-.628.677-1.686 1.588-2.065.013-.07.024-.143.036-.218.029-.183.06-.384.126-.612-.201-.508-.254-1.084-.254-1.656 0-.87.128-1.769.693-2.484.579-.733 1.494-1.124 2.724-1.261 1.206-.134 2.262.034 2.944.765.05.053.096.108.139.165.044-.057.094-.112.143-.165.682-.731 1.738-.899 2.944-.765 1.23.137 2.145.528 2.724 1.261.566.715.693 1.614.693 2.484 0 .572-.053 1.148-.254 1.656.066.228.098.429.126.612.012.076.024.148.037.218.924.385 1.522 1.471 1.591 2.095v1.872c0 .766-3.351 3.795-8.002 3.795Zm0-1.485c2.28 0 4.584-1.11 5.002-1.433V7.862l-.023-.116c-.49.21-1.075.291-1.727.291-1.146 0-2.059-.327-2.71-.991A3.222 3.222 0 0 1 8 6.303a3.24 3.24 0 0 1-.544.743c-.65.664-1.563.991-2.71.991-.652 0-1.236-.081-1.727-.291l-.023.116v4.255c.419.323 2.722 1.433 5.002 1.433ZM6.762 2.83c-.193-.206-.637-.413-1.682-.297-1.019.113-1.479.404-1.713.7-.247.312-.369.789-.369 1.554 0 .793.129 1.171.308 1.371.162.181.519.379 1.442.379.853 0 1.339-.235 1.638-.54.315-.322.527-.827.617-1.553.117-.935-.037-1.395-.241-1.614Zm4.155-.297c-1.044-.116-1.488.091-1.681.297-.204.219-.359.679-.242 1.614.091.726.303 1.231.618 1.553.299.305.784.54 1.638.54.922 0 1.28-.198 1.442-.379.179-.2.308-.578.308-1.371 0-.765-.123-1.242-.37-1.554-.233-.296-.693-.587-1.713-.7Z"></path><path d="M6.25 9.037a.75.75 0 0 1 .75.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 .75-.75Zm4.25.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 1.5 0Z"></path></svg>Copilot for Business</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enterprise-grade AI features</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/enterprise/premium-support" data-analytics-event="{&quot;action&quot;:&quot;premium_support&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;premium_support_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-comment-discussion NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.75 1h8.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 10.25 10H7.061l-2.574 2.573A1.458 1.458 0 0 1 2 11.543V10h-.25A1.75 1.75 0 0 1 0 8.25v-5.5C0 1.784.784 1 1.75 1ZM1.5 2.75v5.5c0 .138.112.25.25.25h1a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h3.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25Zm13 2a.25.25 0 0 0-.25-.25h-.5a.75.75 0 0 1 0-1.5h.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 14.25 12H14v1.543a1.458 1.458 0 0 1-2.487 1.03L9.22 12.28a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l2.22 2.22v-2.19a.75.75 0 0 1 .75-.75h1a.25.25 0 0 0 .25-.25Z"></path></svg>Premium Support</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enterprise-grade 24/7 support</span></span></a></li></ul></div></li></ul></div></div></li><li><a href="https://github.com/pricing" data-analytics-event="{&quot;action&quot;:&quot;pricing&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;pricing&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;pricing_link_pricing_navbar&quot;}" class="MarketingNavigation-module__navLink__hUomM">Pricing</a></li></ul></nav><div class="MarketingHeader-module__ctaContainer__tBmPz"><div class="HeaderSearch-module__searchSlot__oVOUS"><button class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw HeaderSearch-module__trigger__zsF9q" type="button" aria-haspopup="dialog" aria-expanded="false" aria-label="Search or jump to, type / to search" data-analytics-event="{&quot;action&quot;:&quot;searchbar&quot;,&quot;tag&quot;:&quot;input&quot;,&quot;context&quot;:&quot;global&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;searchbar_input_global_navbar&quot;}"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH"><span class="HeaderSearch-module__content__kMpxU"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-search HeaderSearch-module__icon__wcrHX" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path></svg><span class="HeaderSearch-module__label__d1iWG">Search</span><kbd class="HeaderSearch-module__kbd__HNG0o" aria-hidden="true">/</kbd></span></span></span></button><div class="d-none"></div></div><div class="AuthCTAs-module__signInWrap__q2P60"><a class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw AuthCTAs-module__cta__WpwQq AuthCTAs-module__desktopActionGap__UZuXT AuthCTAs-module__hiddenBelowLg__BfKBw" href="/login?return_to=https%3A%2F%2Fgithub.com%2Ffuxingliang%2Fnova-studio%2Fblob%2Fmain%2FBUG_ANALYSIS.md" data-analytics-event="{&quot;action&quot;:&quot;sign_in&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;auth_cta&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;sign_in_link_auth_cta_header&quot;}" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/fuxingliang/nova-studio/blob/main/BUG_ANALYSIS.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="137fe32c5de8902b0575bdec28334d124cde87c0862345c03da61fcc14506c16"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH">Sign in</span></span></a></div><a class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--secondary___gHnw_ Primer_Brand__Button-module__Button--size-small___zQrEw AuthCTAs-module__cta__WpwQq" href="/signup?ref_cta=Sign+up&amp;ref_loc=header+logged+out&amp;ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fblob%2Fshow&amp;source=header-repo&amp;source_repo=fuxingliang%2Fnova-studio" data-analytics-event="{&quot;action&quot;:&quot;sign_up&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;auth_cta&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;sign_up_link_auth_cta_header&quot;}" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/fuxingliang/nova-studio/blob/main/BUG_ANALYSIS.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="137fe32c5de8902b0575bdec28334d124cde87c0862345c03da61fcc14506c16"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-secondary___eJ0_a">Sign up</span></span></a><button class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw HeaderAppearanceSettings-module__trigger__hUheK" type="button" aria-haspopup="dialog" aria-labelledby="_R_fbd_"><span class="Primer_Brand__Button-module__Button__leading-visual___jjtTe" data-testid="Button-leading-visual"><svg data-component="Octicon" focusable="false" aria-hidden="true" class="octicon octicon-sliders Primer_Brand__Button-module__Button__icon-visual____qybb" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M15 2.75a.75.75 0 0 1-.75.75h-4a.75.75 0 0 1 0-1.5h4a.75.75 0 0 1 .75.75Zm-8.5.75v1.25a.75.75 0 0 0 1.5 0v-4a.75.75 0 0 0-1.5 0V2H1.75a.75.75 0 0 0 0 1.5H6.5Zm1.25 5.25a.75.75 0 0 0 0-1.5h-6a.75.75 0 0 0 0 1.5h6ZM15 8a.75.75 0 0 1-.75.75H11.5V10a.75.75 0 1 1-1.5 0V6a.75.75 0 0 1 1.5 0v1.25h2.75A.75.75 0 0 1 15 8Zm-9 5.25v-2a.75.75 0 0 0-1.5 0v1.25H1.75a.75.75 0 0 0 0 1.5H4.5v1.25a.75.75 0 0 0 1.5 0v-2Zm9 0a.75.75 0 0 1-.75.75h-6a.75.75 0 0 1 0-1.5h6a.75.75 0 0 1 .75.75Z"></path></svg></span><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH"></span></span></button><div class="Primer_Brand__Tooltip-module__Tooltip___0Eipx" data-direction="s" aria-hidden="true" id="_R_fbd_">Appearance settings</div></div></div></div></div><div class="MarketingHeader-module__bottomBorder__uZT38" aria-hidden="true"></div></header></div></div>
</react-partial>



      <div hidden="hidden" data-view-component="true" class="js-stale-session-flash stale-session-flash flash flash-warn flash-full">
  
        <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert">
    <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
        <span class="js-stale-session-flash-signed-in" hidden>You signed in with another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span>
        <span class="js-stale-session-flash-signed-out" hidden>You signed out in another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span>
        <span class="js-stale-session-flash-switched" hidden>You switched accounts on another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span>

    <button id="icon-button-1300173b-f961-4829-b70a-bce65ef52bdb" aria-labelledby="tooltip-461d4aca-fd87-4a0d-8e60-6d725d8a04e1" type="button" data-view-component="true" class="Button Button--iconOnly Button--invisible Button--medium flash-close js-flash-close">  <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x Button-visual">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
</button><tool-tip id="tooltip-461d4aca-fd87-4a0d-8e60-6d725d8a04e1" for="icon-button-1300173b-f961-4829-b70a-bce65ef52bdb" popover="manual" data-direction="s" data-type="label" data-view-component="true" class="sr-only position-absolute">Dismiss alert</tool-tip>


  
</div>
    </div>

  <div id="start-of-content" class="show-on-focus"></div>








    <div id="js-flash-container" class="flash-container" data-turbo-replace>






  <template class="js-flash-template">
    
<div class="flash flash-full   {{ className }}">
  <div >
    <button autofocus class="flash-close js-flash-close" type="button" aria-label="Dismiss this message">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
    </button>
    <div aria-atomic="true" role="alert" class="js-flash-alert">
      
      <div>{{ message }}</div>

    </div>
  </div>
</div>
  </template>
</div>


    






  <div
    class="application-main "
    data-commit-hovercards-enabled
    data-discussion-hovercards-enabled
    data-issue-and-pr-hovercards-enabled
    data-project-hovercards-enabled
  >
        <div itemscope itemtype="http://schema.org/SoftwareSourceCode" class="">
    <main id="js-repo-pjax-container" >
      
      








  

    <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ym-6bc2c9bf8112c038.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/sk2-8deeef9351be3911.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ni-3e194d222c7770bf.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/7x-71d30cb240cd901f.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/wwk-ad869086822937b1.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/a1-9f79841ecac1da8e.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/wzg-40a3213b3e83400b.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/5f-64f8e7d5bcbd4787.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/z5-b53a93078d026f1e.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/8h-cef26f68c1331011.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/fq-3ce13a77e863807a.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/a7-596b507bd20acddc.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/xfx-c82d8352413aea0a.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j4-b3a9e87fa7878a98.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/global-nav-bar-29c7aef68ee9db41.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.2d881b4d4a503d1c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/pj.75627bfeb9ceb1da.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/global-nav-bar.2f2560cba06ab359.module.css" />

<react-partial
  partial-name="global-nav-bar"
  data-ssr="true"
  data-attempted-ssr="true"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-partial.embeddedData">{"props":{"contextRegion":{"crumbs":[{"crumb_type":"user","label":"fuxingliang","is_root":false,"href":"/fuxingliang"},{"crumb_type":"repository","label":"nova-studio","is_root":false,"href":"/fuxingliang/nova-studio"}],"localNavigation":[{"id":"code","icon":"code","label":"Code","href":"/fuxingliang/nova-studio","selectedLinks":["repo_source","repo_downloads","repo_commits","repo_releases","repo_tags","repo_branches","repo_packages","repo_deployments","repo_attestations"],"popoverTarget":false,"commandId":"repositories:go-to-code","reactNav":{"appTarget":"code-view","anchor":"code-view-repo-link"},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"issues","icon":"issue-opened","label":"Issues","href":"/fuxingliang/nova-studio/issues","selectedLinks":["repo_issues","repo_labels","repo_milestones"],"count":1,"popoverTarget":false,"commandId":"repositories:go-to-issues","reactNav":{"appTarget":"repo","anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"pull-requests","icon":"git-pull-request","label":"Pull requests","href":"/fuxingliang/nova-studio/pulls","selectedLinks":["repo_pulls","checks"],"count":0,"popoverTarget":false,"commandId":"repositories:go-to-pull-requests","reactNav":{"appTarget":null,"anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"discussions","icon":"comment-discussion","label":"Discussions","href":"/fuxingliang/nova-studio/discussions","selectedLinks":["repo_discussions"],"popoverTarget":false,"commandId":"repositories:go-to-discussions","reactNav":{"appTarget":null,"anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"actions","icon":"play","label":"Actions","href":"/fuxingliang/nova-studio/actions","selectedLinks":["repo_actions"],"popoverTarget":false,"commandId":"repositories:go-to-actions","reactNav":{"appTarget":"actions-workflows","anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"projects","icon":"table","label":"Projects","href":"/fuxingliang/nova-studio/projects","selectedLinks":["repo_projects","new_repo_project","repo_project"],"popoverTarget":false,"commandId":"repositories:go-to-projects","reactNav":{"appTarget":"repo","anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"security-and-quality","icon":"shield","label":"Security and quality","href":"/fuxingliang/nova-studio/security","selectedLinks":["security","overview","alerts","policy","token_scanning","code_scanning"],"count":0,"popoverTarget":false,"commandId":"repositories:go-to-security","reactNav":{"appTarget":null,"anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"insights","icon":"graph","label":"Insights","href":"/fuxingliang/nova-studio/pulse","selectedLinks":["repo_graphs","repo_contributors","dependency_graph","dependabot_updates","pulse","people","community"],"popoverTarget":false,"commandId":"repositories:go-to-insights","reactNav":{"appTarget":null,"anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}}],"localNavigationUpdateChannel":null,"selectedLink":"repo_source"},"owner":null,"headerLogo":{"href":"/","aria-label":"Homepage "},"notifications":{"indicatorMode":"disabled","websocketChannel":null,"fetchIndicatorSrc":"/notifications/indicator","fetchIndicatorEnabled":false},"issues":{"href":"/issues"},"pulls":{"href":"/pulls"},"contributedRepos":{"href":"/repos"},"copilot":{"show":false,"showAgentsButton":false,"showRelaunchAnnouncement":false,"copilotChatUrl":null,"copilotApiUrl":"https://api.githubcopilot.com"},"search":{"show":true,"showCommandPalette":false,"isSearchPage":false,"isJumpToSearch":false,"searchContext":{"scope":"repo:fuxingliang/nova-studio","current_repo_name":"nova-studio","current_repo_nwo":"fuxingliang/nova-studio","user_id":"fuxingliang"}},"commandPalette":null,"enterpriseBar":{"show":false},"globalTransactionalMessage":[],"payloadsUrl":"/_global-navigation/payloads.json?can_toggle_site_admin_and_employee_status=0\u0026is_admin_mode_on=0\u0026is_ui_opted_out=0\u0026show_ui_opt_out=0\u0026v=7","contextRegionUrl":"/_global-navigation/context-region.json"}}</script>
  <div data-target="react-partial.reactRoot"><header aria-label="Global navigation menu" data-component="Stack" class="GlobalNav styles-module__appHeader__YzYWk prc-Stack-Stack-UQ9k6" data-gap="none" data-direction="vertical" data-align="stretch" data-wrap="nowrap" data-justify="start" data-padding="none"><div data-component="Stack" class="prc-Stack-Stack-UQ9k6" data-direction="horizontal" data-align="center" data-wrap="nowrap" data-justify="center" data-padding="none"><div data-testid="top-nav-center" data-component="Stack" class="styles-module__center__R3QRv styles-module__withLocalNavigation__rjTJ_ GlobalNavBar-module__loggedOut__Jv1rk prc-Stack-Stack-UQ9k6" data-gap="condensed" data-direction="horizontal" data-align="stretch" data-wrap="nowrap" data-justify="start" data-padding="normal"><nav class="styles-module__contextRegion__VbSp2 prc-Breadcrumbs-BreadcrumbsBase-3Gb-B" aria-label="Breadcrumbs" data-overflow="menu" data-variant="normal" data-component="Breadcrumbs"><ol class="prc-Breadcrumbs-BreadcrumbsList-BKjpe"><li class="prc-Breadcrumbs-ItemWrapper-k0NLn"><a class="styles-module__contextCrumb__IzGIq prc-Breadcrumbs-Item-jcraJ" data-component="Breadcrumbs.Item" href="/fuxingliang" data-discover="true"><span class="">fuxingliang</span></a></li><li class="prc-Breadcrumbs-ItemWrapper-k0NLn"><a class="styles-module__contextCrumb__IzGIq prc-Breadcrumbs-Item-jcraJ" data-component="Breadcrumbs.Item" href="/fuxingliang/nova-studio" data-discover="true"><span class="styles-module__contextCrumbLast__tI2e3">nova-studio</span></a></li></ol></nav></div><div data-testid="top-nav-right" data-component="Stack" class="styles-module__right__mlBQg styles-module__withLocalNavigation__rjTJ_ styles-module__rightWithResponsiveCreateButton__SKn2W prc-Stack-Stack-UQ9k6" data-gap="condensed" data-direction="horizontal" data-align="center" data-wrap="nowrap" data-justify="start" data-padding="normal"></div></div><h2 class="prc-src-InternalVisuallyHidden-2YaI6">Repository navigation</h2><nav class="prc-components-UnderlineWrapper-eT-Yj prc-UnderlineNav-UnderlineWrapper-GWONT LocalNavigation-module__LocalNavigation__b0Xc0" aria-label="Repository" data-variant="inset" data-overflow-mode="wrap" data-hide-icons-breakpoint="medium"><ul class="prc-UnderlineNav-ItemsList-oj8gN prc-components-UnderlineItemList-xKlKC" role="list"><li role="presentation" aria-hidden="true" class="prc-UnderlineNav-WrapSpacer--aLgz"></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a aria-current="page" data-tab-item="code" data-react-nav="code-view" data-react-nav-anchor="code-view-repo-link" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/fuxingliang/nova-studio" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-code" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path></svg></span><span data-component="text" data-content="Code">Code</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="issues" data-react-nav="repo" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/fuxingliang/nova-studio/issues" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-issue-opened" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"></path></svg></span><span data-component="text" data-content="Issues">Issues</span><span data-component="counter"><span aria-hidden="true" data-variant="secondary" data-component="CounterLabel" class="prc-CounterLabel-CounterLabel-X-kRU">1</span><span class="prc-VisuallyHidden-VisuallyHidden-Q0qSB"> (<!-- -->1<!-- -->)</span></span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="pull-requests" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/fuxingliang/nova-studio/pulls" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-git-pull-request" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25Zm5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354ZM3.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm0 9.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm8.25.75a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Z"></path></svg></span><span data-component="text" data-content="Pull requests">Pull requests</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="discussions" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/fuxingliang/nova-studio/discussions" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-comment-discussion" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.75 1h8.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 10.25 10H7.061l-2.574 2.573A1.458 1.458 0 0 1 2 11.543V10h-.25A1.75 1.75 0 0 1 0 8.25v-5.5C0 1.784.784 1 1.75 1ZM1.5 2.75v5.5c0 .138.112.25.25.25h1a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h3.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25Zm13 2a.25.25 0 0 0-.25-.25h-.5a.75.75 0 0 1 0-1.5h.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 14.25 12H14v1.543a1.458 1.458 0 0 1-2.487 1.03L9.22 12.28a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l2.22 2.22v-2.19a.75.75 0 0 1 .75-.75h1a.25.25 0 0 0 .25-.25Z"></path></svg></span><span data-component="text" data-content="Discussions">Discussions</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="actions" data-react-nav="actions-workflows" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/fuxingliang/nova-studio/actions" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-play" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"></path></svg></span><span data-component="text" data-content="Actions">Actions</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="projects" data-react-nav="repo" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/fuxingliang/nova-studio/projects" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-table" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25ZM6.5 6.5v8h7.75a.25.25 0 0 0 .25-.25V6.5Zm8-1.5V1.75a.25.25 0 0 0-.25-.25H6.5V5Zm-13 1.5v7.75c0 .138.112.25.25.25H5v-8ZM5 5V1.5H1.75a.25.25 0 0 0-.25.25V5Z"></path></svg></span><span data-component="text" data-content="Projects">Projects</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="security-and-quality" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/fuxingliang/nova-studio/security" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-shield" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.467.133a1.748 1.748 0 0 1 1.066 0l5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667Zm.61 1.429a.25.25 0 0 0-.153 0l-5.25 1.68a.25.25 0 0 0-.174.238V7c0 1.358.275 2.666 1.057 3.86.784 1.194 2.121 2.34 4.366 3.297a.196.196 0 0 0 .154 0c2.245-.956 3.582-2.104 4.366-3.298C13.225 9.666 13.5 8.36 13.5 7V3.48a.251.251 0 0 0-.174-.237l-5.25-1.68ZM8.75 4.75v3a.75.75 0 0 1-1.5 0v-3a.75.75 0 0 1 1.5 0ZM9 10.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path></svg></span><span data-component="text" data-content="Security and quality">Security and quality</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="insights" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/fuxingliang/nova-studio/pulse" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-graph" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.5 1.75V13.5h13.75a.75.75 0 0 1 0 1.5H.75a.75.75 0 0 1-.75-.75V1.75a.75.75 0 0 1 1.5 0Zm14.28 2.53-5.25 5.25a.75.75 0 0 1-1.06 0L7 7.06 4.28 9.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.25-3.25a.75.75 0 0 1 1.06 0L10 7.94l4.72-4.72a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path></svg></span><span data-component="text" data-content="Insights">Insights</span></a></li></ul><div class="prc-UnderlineNav-MoreButtonContainer-Dnrq6"><div class="prc-UnderlineNav-MoreButtonDivider-dN0a-"></div><button data-component="overflow-menu-button" type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk prc-UnderlineNav-MoreButton-Y8soj" data-loading="false" data-size="medium" data-variant="invisible" id="_R_2ktp_"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3"><span>More<span class="prc-src-InternalVisuallyHidden-2YaI6"> items</span></span></span></span><span data-component="trailingAction" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></button></div></nav><div class="d-none"></div></header></div>
</react-partial>


  



<turbo-frame id="repo-content-turbo-frame" target="_top" data-turbo-action="advance" class="">
    <div id="repo-content-pjax-container" class="repository-content " >
    



    
      
    








<react-app
  app-name="code-view"
  initial-path="/fuxingliang/nova-studio/blob/main/BUG_ANALYSIS.md"
  style="display: block; min-height: calc(100vh - 64px);"
  data-attempted-ssr="true"
  data-ssr="true"
  data-lazy="false"
  data-alternate="false"
  data-data-router-enabled="true"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-app.embeddedData">{"payload":{"codeViewBlobRoute":{"csv":null,"csvError":null,"headerInfo":{"toc":[{"level":1,"text":"vLLM Launcher 问题分析报告","anchor":"vllm-launcher-问题分析报告","htmlText":"vLLM Launcher 问题分析报告"},{"level":2,"text":"目录","anchor":"目录","htmlText":"目录"},{"level":2,"text":"一、悬浮窗面板（FloatingBar）","anchor":"一悬浮窗面板floatingbar","htmlText":"一、悬浮窗面板（FloatingBar）"},{"level":3,"text":"1.1 右侧 2×2 控制按钮区过于臃肿","anchor":"11-右侧-22-控制按钮区过于臃肿","htmlText":"1.1 右侧 2×2 控制按钮区过于臃肿"},{"level":3,"text":"1.2 信息密度过高，视觉层级混乱","anchor":"12-信息密度过高视觉层级混乱","htmlText":"1.2 信息密度过高，视觉层级混乱"},{"level":3,"text":"1.3 第二行条件性出现导致布局跳动","anchor":"13-第二行条件性出现导致布局跳动","htmlText":"1.3 第二行条件性出现导致布局跳动"},{"level":3,"text":"1.4 模型信息卡固定宽度，信息展示局促","anchor":"14-模型信息卡固定宽度信息展示局促","htmlText":"1.4 模型信息卡固定宽度，信息展示局促"},{"level":3,"text":"1.5 动态背景动画过度","anchor":"15-动态背景动画过度","htmlText":"1.5 动态背景动画过度"},{"level":3,"text":"优化建议：精简 + 分层","anchor":"优化建议精简--分层","htmlText":"优化建议：精简 + 分层"},{"level":2,"text":"二、主题样式","anchor":"二主题样式","htmlText":"二、主题样式"},{"level":3,"text":"2.1 CSS 手动映射维护成本过高","anchor":"21-css-手动映射维护成本过高","htmlText":"2.1 CSS 手动映射维护成本过高"},{"level":3,"text":"2.2 遗漏的浅色主题覆盖","anchor":"22-遗漏的浅色主题覆盖","htmlText":"2.2 遗漏的浅色主题覆盖"},{"level":3,"text":"2.3 Modal 遮罩层浅色失效","anchor":"23-modal-遮罩层浅色失效","htmlText":"2.3 Modal 遮罩层浅色失效"},{"level":3,"text":"2.4 AssistantPanel 代码块浅色对比度不足","anchor":"24-assistantpanel-代码块浅色对比度不足","htmlText":"2.4 AssistantPanel 代码块浅色对比度不足"},{"level":3,"text":"2.5 表面类名语义歧义","anchor":"25-表面类名语义歧义","htmlText":"2.5 表面类名语义歧义"},{"level":3,"text":"2.6 Appearance 页面主题卡片预览对比度不足","anchor":"26-appearance-页面主题卡片预览对比度不足","htmlText":"2.6 Appearance 页面主题卡片预览对比度不足"},{"level":2,"text":"三、Gateway 网关处理","anchor":"三gateway-网关处理","htmlText":"三、Gateway 网关处理"},{"level":3,"text":"3.1 请求体被重复 JSON.parse（P0 性能）","anchor":"31-请求体被重复-jsonparsep0-性能","htmlText":"3.1 请求体被重复 JSON.parse（P0 性能）"},{"level":3,"text":"3.2 SSE .tee() 双份流处理（P0 性能）","anchor":"32-sse-tee-双份流处理p0-性能","htmlText":"3.2 SSE .tee() 双份流处理（P0 性能）"},{"level":3,"text":"3.3 路由匹配 O(n) 线性扫描","anchor":"33-路由匹配-on-线性扫描","htmlText":"3.3 路由匹配 O(n) 线性扫描"},{"level":3,"text":"3.4 Token 估算代码重复","anchor":"34-token-估算代码重复","htmlText":"3.4 Token 估算代码重复"},{"level":3,"text":"3.5 gatewayLogger 和 gatewayRecorder 功能重叠","anchor":"35-gatewaylogger-和-gatewayrecorder-功能重叠","htmlText":"3.5 gatewayLogger 和 gatewayRecorder 功能重叠"},{"level":3,"text":"3.6 activeEntry 注册两次 + 类型断言不安全","anchor":"36-activeentry-注册两次--类型断言不安全","htmlText":"3.6 activeEntry 注册两次 + 类型断言不安全"},{"level":3,"text":"3.7 Anthropic Gateway 兜底路由到第一个实例","anchor":"37-anthropic-gateway-兜底路由到第一个实例","htmlText":"3.7 Anthropic Gateway 兜底路由到第一个实例"},{"level":3,"text":"3.8 系统代理不走统一管线","anchor":"38-系统代理不走统一管线","htmlText":"3.8 系统代理不走统一管线"},{"level":3,"text":"3.9 非流式响应逻辑重复","anchor":"39-非流式响应逻辑重复","htmlText":"3.9 非流式响应逻辑重复"},{"level":3,"text":"3.10 错误处理不精细","anchor":"310-错误处理不精细","htmlText":"3.10 错误处理不精细"},{"level":2,"text":"四、模型实例加锁技术","anchor":"四模型实例加锁技术","htmlText":"四、模型实例加锁技术"},{"level":3,"text":"4.1 运行时热切换未受锁保护（P0 安全漏洞）","anchor":"41-运行时热切换未受锁保护p0-安全漏洞","htmlText":"4.1 运行时热切换未受锁保护（P0 安全漏洞）"},{"level":3,"text":"4.2 实例启动/停止未受锁保护（P0 安全漏洞）","anchor":"42-实例启动停止未受锁保护p0-安全漏洞","htmlText":"4.2 实例启动/停止未受锁保护（P0 安全漏洞）"},{"level":3,"text":"4.3 isPresetLocked 每次读盘（P1 性能）","anchor":"43-ispresetlocked-每次读盘p1-性能","htmlText":"4.3 isPresetLocked 每次读盘（P1 性能）"},{"level":3,"text":"4.4 锁检查与操作的 TOCTOU 窗口","anchor":"44-锁检查与操作的-toctou-窗口","htmlText":"4.4 锁检查与操作的 TOCTOU 窗口"},{"level":3,"text":"4.5 锁粒度单一（仅 boolean）","anchor":"45-锁粒度单一仅-boolean","htmlText":"4.5 锁粒度单一（仅 boolean）"},{"level":3,"text":"4.6 锁状态变更无审计日志","anchor":"46-锁状态变更无审计日志","htmlText":"4.6 锁状态变更无审计日志"},{"level":3,"text":"4.7 并发锁写入无保护","anchor":"47-并发锁写入无保护","htmlText":"4.7 并发锁写入无保护"},{"level":3,"text":"4.8 删除路由中锁检查优先于活动状态检查","anchor":"48-删除路由中锁检查优先于活动状态检查","htmlText":"4.8 删除路由中锁检查优先于活动状态检查"},{"level":3,"text":"4.9 锁检查分散，无中间件","anchor":"49-锁检查分散无中间件","htmlText":"4.9 锁检查分散，无中间件"},{"level":3,"text":"4.10 锁继承关系未定义","anchor":"410-锁继承关系未定义","htmlText":"4.10 锁继承关系未定义"},{"level":2,"text":"五、进程处理（Go 入口）","anchor":"五进程处理go-入口","htmlText":"五、进程处理（Go 入口）"},{"level":3,"text":"5.1 UnrefAllProcesses() 空操作（P0 热退出不可靠）","anchor":"51-unrefallprocesses-空操作p0-热退出不可靠","htmlText":"5.1 UnrefAllProcesses() 空操作（P0 热退出不可靠）"},{"level":3,"text":"5.2 handleStop kill 与 delete 竞态（P0）","anchor":"52-handlestop-kill-与-delete-竞态p0","htmlText":"5.2 handleStop kill 与 delete 竞态（P0）"},{"level":3,"text":"5.3 Node.js 自动重启无上限（P1）","anchor":"53-nodejs-自动重启无上限p1","htmlText":"5.3 Node.js 自动重启无上限（P1）"},{"level":3,"text":"5.4 Go 与 Node.js 进程跟踪双重管理（P1）","anchor":"54-go-与-nodejs-进程跟踪双重管理p1","htmlText":"5.4 Go 与 Node.js 进程跟踪双重管理（P1）"},{"level":3,"text":"5.5 Linux PID 通过日志正则解析获取（P2）","anchor":"55-linux-pid-通过日志正则解析获取p2","htmlText":"5.5 Linux PID 通过日志正则解析获取（P2）"},{"level":3,"text":"5.6 健康探测四层串行，最坏 32 秒/实例（P2）","anchor":"56-健康探测四层串行最坏-32-秒实例p2","htmlText":"5.6 健康探测四层串行，最坏 32 秒/实例（P2）"},{"level":3,"text":"5.7 对账循环 20 秒间隔，崩溃发现延迟高（P2）","anchor":"57-对账循环-20-秒间隔崩溃发现延迟高p2","htmlText":"5.7 对账循环 20 秒间隔，崩溃发现延迟高（P2）"},{"level":3,"text":"5.8 cmd.Wait() goroutine 泄漏（P2）","anchor":"58-cmdwait-goroutine-泄漏p2","htmlText":"5.8 cmd.Wait() goroutine 泄漏（P2）"},{"level":3,"text":"5.9 孤儿进程扫描正则过于宽松（P2）","anchor":"59-孤儿进程扫描正则过于宽松p2","htmlText":"5.9 孤儿进程扫描正则过于宽松（P2）"},{"level":3,"text":"5.10 WSL2 Heartbeat 无条件运行（P2）","anchor":"510-wsl2-heartbeat-无条件运行p2","htmlText":"5.10 WSL2 Heartbeat 无条件运行（P2）"},{"level":3,"text":"5.11 stopNodeServer() 直接 Kill（P2）","anchor":"511-stopnodeserver-直接-killp2","htmlText":"5.11 stopNodeServer() 直接 Kill（P2）"},{"level":3,"text":"5.12 重启流程无事务语义（P2）","anchor":"512-重启流程无事务语义p2","htmlText":"5.12 重启流程无事务语义（P2）"},{"level":2,"text":"六、字体和颜色","anchor":"六字体和颜色","htmlText":"六、字体和颜色"},{"level":3,"text":"6.1 Google Fonts 在线依赖（P0）","anchor":"61-google-fonts-在线依赖p0","htmlText":"6.1 Google Fonts 在线依赖（P0）"},{"level":3,"text":"6.2 AssistantPanel px 字号不跟随缩放（P0）","anchor":"62-assistantpanel-px-字号不跟随缩放p0","htmlText":"6.2 AssistantPanel px 字号不跟随缩放（P0）"},{"level":3,"text":"6.3 Modal 遮罩浅色失效（P0）","anchor":"63-modal-遮罩浅色失效p0","htmlText":"6.3 Modal 遮罩浅色失效（P0）"},{"level":3,"text":"6.4 浅色主题 150 行手动映射（P1）","anchor":"64-浅色主题-150-行手动映射p1","htmlText":"6.4 浅色主题 150 行手动映射（P1）"},{"level":3,"text":"6.5 SparkLineChart 硬编码 hex（P1）","anchor":"65-sparklinechart-硬编码-hexp1","htmlText":"6.5 SparkLineChart 硬编码 hex（P1）"},{"level":3,"text":"6.6 Tailwind 未自定义主题色（P1）","anchor":"66-tailwind-未自定义主题色p1","htmlText":"6.6 Tailwind 未自定义主题色（P1）"},{"level":3,"text":"6.7 主题切换闪烁（P1）","anchor":"67-主题切换闪烁p1","htmlText":"6.7 主题切换闪烁（P1）"},{"level":3,"text":"6.8 字体选择稀少（P2）","anchor":"68-字体选择稀少p2","htmlText":"6.8 字体选择稀少（P2）"},{"level":3,"text":"6.9 等宽字体回退链不一致（P2）","anchor":"69-等宽字体回退链不一致p2","htmlText":"6.9 等宽字体回退链不一致（P2）"},{"level":3,"text":"6.10 滚动条浅色对比度不足（P2）","anchor":"610-滚动条浅色对比度不足p2","htmlText":"6.10 滚动条浅色对比度不足（P2）"},{"level":3,"text":"6.11 根元素文字颜色硬编码（P2）","anchor":"611-根元素文字颜色硬编码p2","htmlText":"6.11 根元素文字颜色硬编码（P2）"},{"level":3,"text":"6.12 auto 主题 mode 固定为 \"dark\"（P2）","anchor":"612-auto-主题-mode-固定为-darkp2","htmlText":"6.12 auto 主题 mode 固定为 \"dark\"（P2）"},{"level":2,"text":"全局优先级汇总","anchor":"全局优先级汇总","htmlText":"全局优先级汇总"}]},"issueTemplate":null,"discussionTemplate":null,"richText":"\u003carticle class=\"markdown-body entry-content container-lg\" itemprop=\"text\"\u003e\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch1 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003evLLM Launcher 问题分析报告\u003c/h1\u003e\u003ca id=\"user-content-vllm-launcher-问题分析报告\" class=\"anchor\" aria-label=\"Permalink: vLLM Launcher 问题分析报告\" href=\"#vllm-launcher-问题分析报告\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003e生成日期：2026-08-08\n状态：待修复\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003chr\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e目录\u003c/h2\u003e\u003ca id=\"user-content-目录\" class=\"anchor\" aria-label=\"Permalink: 目录\" href=\"#目录\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ca href=\"#%E4%B8%80%E6%82%AC%E6%B5%AE%E7%AA%97%E9%9D%A2%E6%9D%BFfloatingbar\"\u003e一、悬浮窗面板（FloatingBar）\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#%E4%BA%8C%E4%B8%BB%E9%A2%98%E6%A0%B7%E5%BC%8F\"\u003e二、主题样式\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#%E4%B8%89gateway-%E7%BD%91%E5%85%B3%E5%A4%84%E7%90%86\"\u003e三、Gateway 网关处理\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#%E5%9B%9B%E6%A8%A1%E5%9E%8B%E5%AE%9E%E4%BE%8B%E5%8A%A0%E9%94%81%E6%8A%80%E6%9C%AF\"\u003e四、模型实例加锁技术\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#%E4%BA%94%E8%BF%9B%E7%A8%8B%E5%A4%84%E7%90%86go-%E5%85%A5%E5%8F%A3\"\u003e五、进程处理（Go 入口）\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#%E5%85%AD%E5%AD%97%E4%BD%93%E5%92%8C%E9%A2%9C%E8%89%B2\"\u003e六、字体和颜色\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e一、悬浮窗面板（FloatingBar）\u003c/h2\u003e\u003ca id=\"user-content-一悬浮窗面板floatingbar\" class=\"anchor\" aria-label=\"Permalink: 一、悬浮窗面板（FloatingBar）\" href=\"#一悬浮窗面板floatingbar\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003e相关文件：\u003ccode\u003evllm-launcher/frontend/src/components/FloatingBar.tsx\u003c/code\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e1.1 右侧 2×2 控制按钮区过于臃肿\u003c/h3\u003e\u003ca id=\"user-content-11-右侧-22-控制按钮区过于臃肿\" class=\"anchor\" aria-label=\"Permalink: 1.1 右侧 2×2 控制按钮区过于臃肿\" href=\"#11-右侧-22-控制按钮区过于臃肿\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e右侧占据 \u003ccode\u003egrid-cols-2 gap-1\u003c/code\u003e 的 2×2 网格（折叠/自动隐藏/收起/恢复），约 56px 宽度，4 个 12-14px 小图标辨识度差，\"折叠\"和\"收起\"语义易混淆。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e1.2 信息密度过高，视觉层级混乱\u003c/h3\u003e\u003ca id=\"user-content-12-信息密度过高视觉层级混乱\" class=\"anchor\" aria-label=\"Permalink: 1.2 信息密度过高，视觉层级混乱\" href=\"#12-信息密度过高视觉层级混乱\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e第一行从左到右塞了 10+ 个元素（Logo → 停止 → 思考下拉框 → 阶段指示器 → TPS → Token → 预填充 → 进度条 → 耗时 → 实例切换器 → 运行计数 → 启动计数），无主次分组。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e1.3 第二行条件性出现导致布局跳动\u003c/h3\u003e\u003ca id=\"user-content-13-第二行条件性出现导致布局跳动\" class=\"anchor\" aria-label=\"Permalink: 1.3 第二行条件性出现导致布局跳动\" href=\"#13-第二行条件性出现导致布局跳动\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e第二行（模型信息卡 + 压缩下拉框）在 \u003ccode\u003einfoCollapsed\u003c/code\u003e 或 \u003ccode\u003eshowStartup\u003c/code\u003e 时整行消失，横栏内容上下跳动。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e1.4 模型信息卡固定宽度，信息展示局促\u003c/h3\u003e\u003ca id=\"user-content-14-模型信息卡固定宽度信息展示局促\" class=\"anchor\" aria-label=\"Permalink: 1.4 模型信息卡固定宽度，信息展示局促\" href=\"#14-模型信息卡固定宽度信息展示局促\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e模型名最多 130px，上下文进度条 52px，KV cache 两行小字，整体拥挤。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e1.5 动态背景动画过度\u003c/h3\u003e\u003ca id=\"user-content-15-动态背景动画过度\" class=\"anchor\" aria-label=\"Permalink: 1.5 动态背景动画过度\" href=\"#15-动态背景动画过度\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e推理时有扫描线、粒子流、波浪条、呼吸发光、能量脉冲等多层动画叠加，在 92px 高的横栏里分散注意力。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e优化建议：精简 + 分层\u003c/h3\u003e\u003ca id=\"user-content-优化建议精简--分层\" class=\"anchor\" aria-label=\"Permalink: 优化建议：精简 + 分层\" href=\"#优化建议精简--分层\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e优先级\u003c/th\u003e\n\u003cth\u003e内容\u003c/th\u003e\n\u003cth\u003e处理方式\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eP0（常驻）\u003c/td\u003e\n\u003ctd\u003e阶段状态 + TPS + 模型名\u003c/td\u003e\n\u003ctd\u003e永远可见\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eP1（常驻）\u003c/td\u003e\n\u003ctd\u003e停止按钮 + 实例切换\u003c/td\u003e\n\u003ctd\u003e永远可见\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eP2（按需）\u003c/td\u003e\n\u003ctd\u003e思考模式 / 压缩模式\u003c/td\u003e\n\u003ctd\u003e折叠到菜单或悬停展开\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eP3（按需）\u003c/td\u003e\n\u003ctd\u003e上下文使用量 / KV Cache / 进度条\u003c/td\u003e\n\u003ctd\u003e悬停或点击展开详情面板\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eP4（低频）\u003c/td\u003e\n\u003ctd\u003e恢复窗口 / 自动隐藏\u003c/td\u003e\n\u003ctd\u003e合并到右键菜单或单按钮\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003chr\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e二、主题样式\u003c/h2\u003e\u003ca id=\"user-content-二主题样式\" class=\"anchor\" aria-label=\"Permalink: 二、主题样式\" href=\"#二主题样式\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003e相关文件：\u003ccode\u003evllm-launcher/frontend/src/index.css\u003c/code\u003e、\u003ccode\u003evllm-launcher/frontend/src/lib/theme.ts\u003c/code\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e2.1 CSS 手动映射维护成本过高\u003c/h3\u003e\u003ca id=\"user-content-21-css-手动映射维护成本过高\" class=\"anchor\" aria-label=\"Permalink: 2.1 CSS 手动映射维护成本过高\" href=\"#21-css-手动映射维护成本过高\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eindex.css 约 200 行手动 \u003ccode\u003ehtml[data-theme-mode=\"light\"] .text-xxx { color: ... }\u003c/code\u003e 映射，每新增颜色类需手动添加覆盖规则，容易遗漏。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e2.2 遗漏的浅色主题覆盖\u003c/h3\u003e\u003ca id=\"user-content-22-遗漏的浅色主题覆盖\" class=\"anchor\" aria-label=\"Permalink: 2.2 遗漏的浅色主题覆盖\" href=\"#22-遗漏的浅色主题覆盖\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e严重性\u003c/th\u003e\n\u003cth\u003e文件\u003c/th\u003e\n\u003cth\u003e类名\u003c/th\u003e\n\u003cth\u003e问题\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e高\u003c/td\u003e\n\u003ctd\u003eindex.css#L97\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ebg-[#050912]\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e.terminal-panel\u003c/code\u003e 硬编码 hex\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e高\u003c/td\u003e\n\u003ctd\u003eDiagnosticCards.tsx\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ebg-black\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e纯黑背景浅色下不可见\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e高\u003c/td\u003e\n\u003ctd\u003eDownloads.tsx\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ebg-slate-900/80\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eCSS 仅覆盖 \u003ccode\u003e/60\u003c/code\u003e 和 \u003ccode\u003e/70\u003c/code\u003e 变体\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e高\u003c/td\u003e\n\u003ctd\u003eFinetune.tsx\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ebg-slate-950\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e无透明度变体未覆盖\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e高\u003c/td\u003e\n\u003ctd\u003eFloatingBar.tsx\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ebg-slate-950/95\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e提示框背景未覆盖\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e中\u003c/td\u003e\n\u003ctd\u003eInferenceTimeline.tsx\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ebg-slate-800/90\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eCSS 仅覆盖 \u003ccode\u003e/40\u003c/code\u003e、\u003ccode\u003e/60\u003c/code\u003e、\u003ccode\u003e/80\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e中\u003c/td\u003e\n\u003ctd\u003eAssistantPanel.tsx\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eborder-slate-700\u003c/code\u003e、\u003ccode\u003eborder-slate-600\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e边框浅色下可能消失\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e2.3 Modal 遮罩层浅色失效\u003c/h3\u003e\u003ca id=\"user-content-23-modal-遮罩层浅色失效\" class=\"anchor\" aria-label=\"Permalink: 2.3 Modal 遮罩层浅色失效\" href=\"#23-modal-遮罩层浅色失效\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e多个组件使用 \u003ccode\u003ebg-black/60\u003c/code\u003e 遮罩，映射为 \u003ccode\u003evar(--app-inset-bg)\u003c/code\u003e，浅色主题下变为白色半透明，\"压暗\"效果完全失效。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e涉及文件：\u003ccode\u003eAddModelDialog.tsx\u003c/code\u003e、\u003ccode\u003eControlForm.tsx\u003c/code\u003e、\u003ccode\u003eConfirmDialog.tsx\u003c/code\u003e、\u003ccode\u003eCreateInstanceDialog.tsx\u003c/code\u003e、\u003ccode\u003eShutdownDialog.tsx\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e2.4 AssistantPanel 代码块浅色对比度不足\u003c/h3\u003e\u003ca id=\"user-content-24-assistantpanel-代码块浅色对比度不足\" class=\"anchor\" aria-label=\"Permalink: 2.4 AssistantPanel 代码块浅色对比度不足\" href=\"#24-assistantpanel-代码块浅色对比度不足\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eAssistantPanel.css 代码块背景浅色下为 \u003ccode\u003e#ffffff\u003c/code\u003e，与面板背景无区分度；语法高亮无成熟浅色主题。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e2.5 表面类名语义歧义\u003c/h3\u003e\u003ca id=\"user-content-25-表面类名语义歧义\" class=\"anchor\" aria-label=\"Permalink: 2.5 表面类名语义歧义\" href=\"#25-表面类名语义歧义\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-css notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\".bg-white\\/5 { background-color: var(--app-card-bg, ...); }\"\u003e\u003cpre\u003e.\u003cspan class=\"pl-c1\"\u003ebg-white\\/\u003c/span\u003e5 { \u003cspan class=\"pl-c1\"\u003ebackground-color\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e \u003cspan class=\"pl-en\"\u003evar\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003e--app-card-bg\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e ...); }\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003ebg-white/5\u003c/code\u003e 暗示白色，实际随主题变化，降低类名可读性。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e2.6 Appearance 页面主题卡片预览对比度不足\u003c/h3\u003e\u003ca id=\"user-content-26-appearance-页面主题卡片预览对比度不足\" class=\"anchor\" aria-label=\"Permalink: 2.6 Appearance 页面主题卡片预览对比度不足\" href=\"#26-appearance-页面主题卡片预览对比度不足\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e主题卡片预览区域（48px 高）在浅色主题下 \u003ccode\u003ebg-white/5\u003c/code\u003e 可能与浅色 deck 渐变对比度不足。\u003c/p\u003e\n\u003chr\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e三、Gateway 网关处理\u003c/h2\u003e\u003ca id=\"user-content-三gateway-网关处理\" class=\"anchor\" aria-label=\"Permalink: 三、Gateway 网关处理\" href=\"#三gateway-网关处理\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003e相关文件：\u003ccode\u003elauncher/api/routes/gateway.ts\u003c/code\u003e、\u003ccode\u003elauncher/api/middleware/gatewayLogger.ts\u003c/code\u003e、\u003ccode\u003elauncher/api/services/gatewayRecorder.ts\u003c/code\u003e、\u003ccode\u003elauncher/api/services/contextCompressor.ts\u003c/code\u003e、\u003ccode\u003elauncher/api/routes/anthropicGateway.ts\u003c/code\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e3.1 请求体被重复 JSON.parse（P0 性能）\u003c/h3\u003e\u003ca id=\"user-content-31-请求体被重复-jsonparsep0-性能\" class=\"anchor\" aria-label=\"Permalink: 3.1 请求体被重复 JSON.parse（P0 性能）\" href=\"#31-请求体被重复-jsonparsep0-性能\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eforwardGatewayRequest\u003c/code\u003e 中请求体被解析至少 \u003cstrong\u003e8 次\u003c/strong\u003e：\u003c/p\u003e\n\u003cdiv class=\"snippet-clipboard-content notranslate position-relative overflow-auto\" data-snippet-clipboard-copy-content=\"1. recordRequest → parseJsonSafely\n2. truncateOversizedToolResults → JSON.parse\n3. compressChatContext → JSON.parse\n4. injectReasoningIntoBody → JSON.parse\n5. injectStreamOptions → JSON.parse\n6. 检测 isStream → JSON.parse\n7. 获取 modelName → JSON.parse\n8. shouldProcessReasoning → JSON.parse\"\u003e\u003cpre class=\"notranslate\"\u003e\u003ccode\u003e1. recordRequest → parseJsonSafely\n2. truncateOversizedToolResults → JSON.parse\n3. compressChatContext → JSON.parse\n4. injectReasoningIntoBody → JSON.parse\n5. injectStreamOptions → JSON.parse\n6. 检测 isStream → JSON.parse\n7. 获取 modelName → JSON.parse\n8. shouldProcessReasoning → JSON.parse\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e每次都是 \u003ccode\u003eJSON.parse → 处理 → JSON.stringify → 再 parse\u003c/code\u003e。大上下文请求（几十 KB ~ MB 级）明显延迟。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 入口处解析一次，传递 \u003ccode\u003eparsedBody: Record\u0026lt;string, unknown\u0026gt;\u003c/code\u003e 对象，仅在转发前 stringify 一次。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e3.2 SSE \u003ccode\u003e.tee()\u003c/code\u003e 双份流处理（P0 性能）\u003c/h3\u003e\u003ca id=\"user-content-32-sse-tee-双份流处理p0-性能\" class=\"anchor\" aria-label=\"Permalink: 3.2 SSE .tee() 双份流处理（P0 性能）\" href=\"#32-sse-tee-双份流处理p0-性能\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-ts notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"const [upstreamForResponse, upstreamForLog] = upstreamReadableStream.tee();\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003econst\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e[\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eupstreamForResponse\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eupstreamForLog\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e]\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eupstreamReadableStream\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003etee\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e每个 byte 被处理两次（日志 + 响应），高 TPS 下翻倍 CPU 和内存。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 去掉 \u003ccode\u003e.tee()\u003c/code\u003e，将日志采集合并到主处理管线，单遍处理。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e3.3 路由匹配 O(n) 线性扫描\u003c/h3\u003e\u003ca id=\"user-content-33-路由匹配-on-线性扫描\" class=\"anchor\" aria-label=\"Permalink: 3.3 路由匹配 O(n) 线性扫描\" href=\"#33-路由匹配-on-线性扫描\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-ts notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"function findGatewayRouteByModel(modelName) {\n  for (const status of getInstanceStatuses()) {  // O(n)\n    const aliases = getGatewayAliases(status).map(...);  // 每次都重新生成\n    if (aliases.includes(normalized)) { ... }\n  }\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003efunction\u003c/span\u003e \u003cspan class=\"pl-en\"\u003efindGatewayRouteByModel\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003emodelName\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"pl-k\"\u003efor\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-k\"\u003econst\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003estatus\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eof\u003c/span\u003e \u003cspan class=\"pl-en\"\u003egetInstanceStatuses\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e  \u003cspan class=\"pl-c\"\u003e// O(n)\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003econst\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ealiases\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-en\"\u003egetGatewayAliases\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003estatus\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003emap\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e...\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e  \u003cspan class=\"pl-c\"\u003e// 每次都重新生成\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003eif\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003ealiases\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eincludes\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003enormalized\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e ... \u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 维护 \u003ccode\u003eMap\u0026lt;modelAlias, GatewayRouteMatch\u0026gt;\u003c/code\u003e 路由表，实例启停时更新，查找 O(1)。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e3.4 Token 估算代码重复\u003c/h3\u003e\u003ca id=\"user-content-34-token-估算代码重复\" class=\"anchor\" aria-label=\"Permalink: 3.4 Token 估算代码重复\" href=\"#34-token-估算代码重复\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eestimateTokensFromText\u003c/code\u003e 在两个文件中各实现一遍：\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003egateway.ts\u003c/code\u003e 第 588 行\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003econtextCompressor.ts\u003c/code\u003e 第 49 行\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e代码完全相同，维护两份容易不一致。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 提取到独立的 \u003ccode\u003etokenEstimator.ts\u003c/code\u003e 工具模块。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e3.5 gatewayLogger 和 gatewayRecorder 功能重叠\u003c/h3\u003e\u003ca id=\"user-content-35-gatewaylogger-和-gatewayrecorder-功能重叠\" class=\"anchor\" aria-label=\"Permalink: 3.5 gatewayLogger 和 gatewayRecorder 功能重叠\" href=\"#35-gatewaylogger-和-gatewayrecorder-功能重叠\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e\u003c/th\u003e\n\u003cth\u003egatewayLogger\u003c/th\u003e\n\u003cth\u003egatewayRecorder\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e存储\u003c/td\u003e\n\u003ctd\u003e内存数组（最多 50 条）\u003c/td\u003e\n\u003ctd\u003e磁盘 JSONL（最多 2GB）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e内容\u003c/td\u003e\n\u003ctd\u003e请求头 + 截断 body + SSE preview\u003c/td\u003e\n\u003ctd\u003e完整 rawBody + 响应指标\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e用途\u003c/td\u003e\n\u003ctd\u003e调试推理过程\u003c/td\u003e\n\u003ctd\u003e分析 KV Cache / 客户端行为\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003cp dir=\"auto\"\u003e两者各自独立采集相同数据（model、messages、usage 等）。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 合并为单一录制管线。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e3.6 activeEntry 注册两次 + 类型断言不安全\u003c/h3\u003e\u003ca id=\"user-content-36-activeentry-注册两次--类型断言不安全\" class=\"anchor\" aria-label=\"Permalink: 3.6 activeEntry 注册两次 + 类型断言不安全\" href=\"#36-activeentry-注册两次--类型断言不安全\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-ts notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"// 第 819 行（回调内）\nregisterActiveUpstreamRequest(route.instanceId, activeEntry);\n// 第 1035 行（回调外）\nregisterActiveUpstreamRequest(route.instanceId, activeEntry);\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e// 第 819 行（回调内）\u003c/span\u003e\n\u003cspan class=\"pl-en\"\u003eregisterActiveUpstreamRequest\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eroute\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003einstanceId\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eactiveEntry\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e// 第 1035 行（回调外）\u003c/span\u003e\n\u003cspan class=\"pl-en\"\u003eregisterActiveUpstreamRequest\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eroute\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003einstanceId\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eactiveEntry\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 只在 \u003ccode\u003ehttp.request()\u003c/code\u003e 返回后立即注册一次。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e3.7 Anthropic Gateway 兜底路由到第一个实例\u003c/h3\u003e\u003ca id=\"user-content-37-anthropic-gateway-兜底路由到第一个实例\" class=\"anchor\" aria-label=\"Permalink: 3.7 Anthropic Gateway 兜底路由到第一个实例\" href=\"#37-anthropic-gateway-兜底路由到第一个实例\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-ts notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"const targetModel = matched?.modelId ?? instances[0]?.modelId;\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003econst\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003etargetModel\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ematched\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e?.\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003emodelId\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e??\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003einstances\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e[\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e]\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e?.\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003emodelId\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e匹配失败时静默回退到第一个实例，可能路由到错误模型。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 返回明确 404 或按能力智能路由。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e3.8 系统代理不走统一管线\u003c/h3\u003e\u003ca id=\"user-content-38-系统代理不走统一管线\" class=\"anchor\" aria-label=\"Permalink: 3.8 系统代理不走统一管线\" href=\"#38-系统代理不走统一管线\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e系统代理劫持后走独立的 \u003ccode\u003eforwardToGateway\u003c/code\u003e 函数，不经过 \u003ccode\u003eforwardGatewayRequest\u003c/code\u003e，导致上下文压缩、推理处理等功能对代理路径不生效。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e3.9 非流式响应逻辑重复\u003c/h3\u003e\u003ca id=\"user-content-39-非流式响应逻辑重复\" class=\"anchor\" aria-label=\"Permalink: 3.9 非流式响应逻辑重复\" href=\"#39-非流式响应逻辑重复\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003ereasoningConfig.enabled\u003c/code\u003e 和 \u003ccode\u003e!enabled\u003c/code\u003e 两条路径都调用了 \u003ccode\u003ecaptureInferenceMetrics\u003c/code\u003e、\u003ccode\u003erecorderSession?.captureUsage\u003c/code\u003e 等，逻辑重复。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e3.10 错误处理不精细\u003c/h3\u003e\u003ca id=\"user-content-310-错误处理不精细\" class=\"anchor\" aria-label=\"Permalink: 3.10 错误处理不精细\" href=\"#310-错误处理不精细\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e所有上游问题（ECONNREFUSED、ETIMEDOUT、引擎 5xx）都返回 502，客户端无法区分错误类型。\u003c/p\u003e\n\u003chr\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e四、模型实例加锁技术\u003c/h2\u003e\u003ca id=\"user-content-四模型实例加锁技术\" class=\"anchor\" aria-label=\"Permalink: 四、模型实例加锁技术\" href=\"#四模型实例加锁技术\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003e相关文件：\u003ccode\u003elauncher/api/services/instanceManager.ts\u003c/code\u003e、\u003ccode\u003elauncher/api/services/presetStore.ts\u003c/code\u003e、\u003ccode\u003elauncher/api/services/cardMeta.ts\u003c/code\u003e、\u003ccode\u003elauncher/api/routes/instances.ts\u003c/code\u003e、\u003ccode\u003elauncher/api/routes/presets.ts\u003c/code\u003e、\u003ccode\u003elauncher/api/types.ts\u003c/code\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e4.1 运行时热切换未受锁保护（P0 安全漏洞）\u003c/h3\u003e\u003ca id=\"user-content-41-运行时热切换未受锁保护p0-安全漏洞\" class=\"anchor\" aria-label=\"Permalink: 4.1 运行时热切换未受锁保护（P0 安全漏洞）\" href=\"#41-运行时热切换未受锁保护p0-安全漏洞\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003ePATCH /api/instances/:id/runtime/settings\u003c/code\u003e（instances.ts 第 275 行）没有锁检查，可修改 reasoning/temperature/topP/stop/maxTokens/compression——这些正是锁要保护的参数。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e4.2 实例启动/停止未受锁保护（P0 安全漏洞）\u003c/h3\u003e\u003ca id=\"user-content-42-实例启动停止未受锁保护p0-安全漏洞\" class=\"anchor\" aria-label=\"Permalink: 4.2 实例启动/停止未受锁保护（P0 安全漏洞）\" href=\"#42-实例启动停止未受锁保护p0-安全漏洞\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-ts notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"// 无锁检查\nrouter.post(\u0026quot;/api/instances/:id/stop\u0026quot;, ...)\nrouter.post(\u0026quot;/api/instances/:id/restart\u0026quot;, ...)\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e// 无锁检查\u003c/span\u003e\n\u003cspan class=\"pl-s1\"\u003erouter\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003epost\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"/api/instances/:id/stop\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e ...\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-s1\"\u003erouter\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003epost\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"/api/instances/:id/restart\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e ...\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e4.3 \u003ccode\u003eisPresetLocked\u003c/code\u003e 每次读盘（P1 性能）\u003c/h3\u003e\u003ca id=\"user-content-43-ispresetlocked-每次读盘p1-性能\" class=\"anchor\" aria-label=\"Permalink: 4.3 isPresetLocked 每次读盘（P1 性能）\" href=\"#43-ispresetlocked-每次读盘p1-性能\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-ts notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"export async function isPresetLocked(id: string): Promise\u0026lt;boolean\u0026gt; {\n  const data = await readPresets();  // ← 磁盘 IO\n  return data.presets.find(...)?.meta?.locked === true;\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003eexport\u003c/span\u003e \u003cspan class=\"pl-k\"\u003easync\u003c/span\u003e \u003cspan class=\"pl-k\"\u003efunction\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eisPresetLocked\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e: \u003cspan class=\"pl-smi\"\u003estring\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e: \u003cspan class=\"pl-smi\"\u003ePromise\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eboolean\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"pl-k\"\u003econst\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003edata\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eawait\u003c/span\u003e \u003cspan class=\"pl-en\"\u003ereadPresets\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e  \u003cspan class=\"pl-c\"\u003e// ← 磁盘 IO\u003c/span\u003e\n  \u003cspan class=\"pl-k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003edata\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003epresets\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003efind\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e...\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e?.\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003emeta\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e?.\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003elocked\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e===\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003etrue\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e而 \u003ccode\u003eisInstanceLocked\u003c/code\u003e 是纯内存操作。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 预设数据缓存到内存，锁检查走内存路径。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e4.4 锁检查与操作的 TOCTOU 窗口\u003c/h3\u003e\u003ca id=\"user-content-44-锁检查与操作的-toctou-窗口\" class=\"anchor\" aria-label=\"Permalink: 4.4 锁检查与操作的 TOCTOU 窗口\" href=\"#44-锁检查与操作的-toctou-窗口\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e前端先检查锁再执行保存，存在竞态窗口。后端虽有最终拦截，但两套错误提示不一致。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 前端去掉锁检查，完全依赖后端 403 统一处理。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e4.5 锁粒度单一（仅 boolean）\u003c/h3\u003e\u003ca id=\"user-content-45-锁粒度单一仅-boolean\" class=\"anchor\" aria-label=\"Permalink: 4.5 锁粒度单一（仅 boolean）\" href=\"#45-锁粒度单一仅-boolean\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-ts notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"export type CardMeta = {\n  locked: boolean;  // 要么全锁要么全不锁\n  // ...\n};\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003eexport\u003c/span\u003e \u003cspan class=\"pl-k\"\u003etype\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eCardMeta\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"pl-c1\"\u003elocked\u003c/span\u003e: \u003cspan class=\"pl-smi\"\u003eboolean\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e  \u003cspan class=\"pl-c\"\u003e// 要么全锁要么全不锁\u003c/span\u003e\n  \u003cspan class=\"pl-c\"\u003e// ...\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 扩展为细粒度策略：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-ts notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"export type LockPolicy = {\n  preventDelete: boolean;\n  preventConfigChange: boolean;\n  preventLifecycle: boolean;\n};\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003eexport\u003c/span\u003e \u003cspan class=\"pl-k\"\u003etype\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eLockPolicy\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"pl-c1\"\u003epreventDelete\u003c/span\u003e: \u003cspan class=\"pl-smi\"\u003eboolean\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"pl-c1\"\u003epreventConfigChange\u003c/span\u003e: \u003cspan class=\"pl-smi\"\u003eboolean\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"pl-c1\"\u003epreventLifecycle\u003c/span\u003e: \u003cspan class=\"pl-smi\"\u003eboolean\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e4.6 锁状态变更无审计日志\u003c/h3\u003e\u003ca id=\"user-content-46-锁状态变更无审计日志\" class=\"anchor\" aria-label=\"Permalink: 4.6 锁状态变更无审计日志\" href=\"#46-锁状态变更无审计日志\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eupdateCardMeta\u003c/code\u003e 直接修改内存 + 落盘，无 \u003ccode\u003ecreateInstanceLog\u003c/code\u003e 调用。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 锁状态变更时写实例日志。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e4.7 并发锁写入无保护\u003c/h3\u003e\u003ca id=\"user-content-47-并发锁写入无保护\" class=\"anchor\" aria-label=\"Permalink: 4.7 并发锁写入无保护\" href=\"#47-并发锁写入无保护\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e多个请求同时修改同一实例的 meta 和 config 时，锁检查和修改分属不同异步操作，中间可能插入其他请求。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e per-instance 串行化队列。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e4.8 删除路由中锁检查优先于活动状态检查\u003c/h3\u003e\u003ca id=\"user-content-48-删除路由中锁检查优先于活动状态检查\" class=\"anchor\" aria-label=\"Permalink: 4.8 删除路由中锁检查优先于活动状态检查\" href=\"#48-删除路由中锁检查优先于活动状态检查\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-ts notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"if (isInstanceLocked(instanceId)) {  // 先检查锁 → 403\n  ...\n}\nif (status.phase === \u0026quot;running\u0026quot; || ...) {  // 再检查活动 → 409\n  ...\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003eif\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eisInstanceLocked\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003einstanceId\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e  \u003cspan class=\"pl-c\"\u003e// 先检查锁 → 403\u003c/span\u003e\n  ...\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003eif\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003estatus\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003ephase\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e===\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"running\"\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e||\u003c/span\u003e ...\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e  \u003cspan class=\"pl-c\"\u003e// 再检查活动 → 409\u003c/span\u003e\n  ...\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e运行中且加锁的实例返回 403 而非 409，用户困惑。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 先检查活动状态，再检查锁。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e4.9 锁检查分散，无中间件\u003c/h3\u003e\u003ca id=\"user-content-49-锁检查分散无中间件\" class=\"anchor\" aria-label=\"Permalink: 4.9 锁检查分散，无中间件\" href=\"#49-锁检查分散无中间件\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eisPresetLocked\u003c/code\u003e 检查分散在 \u003ccode\u003epresets.ts\u003c/code\u003e 多处，\u003ccode\u003eisInstanceLocked\u003c/code\u003e 同理，新增路由时容易遗漏。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 提取为 Express 中间件。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e4.10 锁继承关系未定义\u003c/h3\u003e\u003ca id=\"user-content-410-锁继承关系未定义\" class=\"anchor\" aria-label=\"Permalink: 4.10 锁继承关系未定义\" href=\"#410-锁继承关系未定义\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e实例从预设创建时 \u003ccode\u003efreshInstanceMeta\u003c/code\u003e 总是重置 \u003ccode\u003elocked: false\u003c/code\u003e，预设加锁后创建的实例默认未加锁，行为合理但无文档说明。\u003c/p\u003e\n\u003chr\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e五、进程处理（Go 入口）\u003c/h2\u003e\u003ca id=\"user-content-五进程处理go-入口\" class=\"anchor\" aria-label=\"Permalink: 五、进程处理（Go 入口）\" href=\"#五进程处理go-入口\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003e相关文件：\u003ccode\u003evllm-launcher/main.go\u003c/code\u003e、\u003ccode\u003elauncher/api/services/instanceLifecycle.ts\u003c/code\u003e、\u003ccode\u003elauncher/api/services/instanceManager.ts\u003c/code\u003e、\u003ccode\u003elauncher/api/services/instanceRegistry.ts\u003c/code\u003e、\u003ccode\u003elauncher/api/services/wslProbe.ts\u003c/code\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e5.1 \u003ccode\u003eUnrefAllProcesses()\u003c/code\u003e 空操作（P0 热退出不可靠）\u003c/h3\u003e\u003ca id=\"user-content-51-unrefallprocesses-空操作p0-热退出不可靠\" class=\"anchor\" aria-label=\"Permalink: 5.1 UnrefAllProcesses() 空操作（P0 热退出不可靠）\" href=\"#51-unrefallprocesses-空操作p0-热退出不可靠\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-go notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"func (m *WslManager) UnrefAllProcesses() {\n    m.mu.Lock()\n    for id, proc := range m.processes {\n        log.Printf(\u0026quot;[WSL-MGR] Detaching instance %s\u0026quot;, id, proc.Pid)\n    }\n    m.mu.Unlock()\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003efunc\u003c/span\u003e (\u003cspan class=\"pl-s1\"\u003em\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e*\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eWslManager\u003c/span\u003e) \u003cspan class=\"pl-c1\"\u003eUnrefAllProcesses\u003c/span\u003e() {\n    \u003cspan class=\"pl-s1\"\u003em\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003emu\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eLock\u003c/span\u003e()\n    \u003cspan class=\"pl-k\"\u003efor\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eproc\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e:=\u003c/span\u003e \u003cspan class=\"pl-k\"\u003erange\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003em\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eprocesses\u003c/span\u003e {\n        \u003cspan class=\"pl-s1\"\u003elog\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ePrintf\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"[WSL-MGR] Detaching instance %s\"\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eproc\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ePid\u003c/span\u003e)\n    }\n    \u003cspan class=\"pl-s1\"\u003em\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003emu\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eUnlock\u003c/span\u003e()\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e只打日志，没有设置 \u003ccode\u003eproc.Detached = true\u003c/code\u003e 或释放 \u003ccode\u003eproc.Cmd\u003c/code\u003e。Go 进程退出时未 detached 的子进程会被级联杀死，热退出实际上可能杀掉模型。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e5.2 \u003ccode\u003ehandleStop\u003c/code\u003e kill 与 delete 竞态（P0）\u003c/h3\u003e\u003ca id=\"user-content-52-handlestop-kill-与-delete-竞态p0\" class=\"anchor\" aria-label=\"Permalink: 5.2 handleStop kill 与 delete 竞态（P0）\" href=\"#52-handlestop-kill-与-delete-竞态p0\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-go notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"go func(pid int) {\n    wslCommand(\u0026quot;bash\u0026quot;, \u0026quot;-c\u0026quot;, fmt.Sprintf(\u0026quot;kill %d ...\u0026quot;, pid)).Run()\n}(proc.LinuxPid)\ndelete(m.processes, req.InstanceID)  // 立即删除\njson.NewEncoder(w).Encode(StartResponse{Success: true})  // 立即返回\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003ego\u003c/span\u003e \u003cspan class=\"pl-k\"\u003efunc\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003epid\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eint\u003c/span\u003e) {\n    \u003cspan class=\"pl-s1\"\u003ewslCommand\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"bash\"\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e\"-c\"\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003efmt\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eSprintf\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"kill %d ...\"\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003epid\u003c/span\u003e)).\u003cspan class=\"pl-c1\"\u003eRun\u003c/span\u003e()\n}(\u003cspan class=\"pl-s1\"\u003eproc\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eLinuxPid\u003c/span\u003e)\n\u003cspan class=\"pl-s1\"\u003edelete\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003em\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eprocesses\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003ereq\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eInstanceID\u003c/span\u003e)  \u003cspan class=\"pl-c\"\u003e// 立即删除\u003c/span\u003e\n\u003cspan class=\"pl-s1\"\u003ejson\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eNewEncoder\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003ew\u003c/span\u003e).\u003cspan class=\"pl-c1\"\u003eEncode\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eStartResponse\u003c/span\u003e{\u003cspan class=\"pl-s1\"\u003eSuccess\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003etrue\u003c/span\u003e})  \u003cspan class=\"pl-c\"\u003e// 立即返回\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eKill 异步执行，Map 立即删除，响应立即返回。此时进程可能还在运行，端口仍被占用。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e5.3 Node.js 自动重启无上限（P1）\u003c/h3\u003e\u003ca id=\"user-content-53-nodejs-自动重启无上限p1\" class=\"anchor\" aria-label=\"Permalink: 5.3 Node.js 自动重启无上限（P1）\" href=\"#53-nodejs-自动重启无上限p1\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-go notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"restartCount := 0\nfor {\n    cmd.Wait()\n    restartCount++\n    // 无上限，无限重启\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-s1\"\u003erestartCount\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e:=\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003efor\u003c/span\u003e {\n    \u003cspan class=\"pl-s1\"\u003ecmd\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eWait\u003c/span\u003e()\n    \u003cspan class=\"pl-s1\"\u003erestartCount\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e++\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// 无上限，无限重启\u003c/span\u003e\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eserver.cjs\u003c/code\u003e 启动错误时无限重启，每秒 2 次。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 添加上限（10 次）或退避策略。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e5.4 Go 与 Node.js 进程跟踪双重管理（P1）\u003c/h3\u003e\u003ca id=\"user-content-54-go-与-nodejs-进程跟踪双重管理p1\" class=\"anchor\" aria-label=\"Permalink: 5.4 Go 与 Node.js 进程跟踪双重管理（P1）\" href=\"#54-go-与-nodejs-进程跟踪双重管理p1\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e跟踪方\u003c/th\u003e\n\u003cth\u003e存储\u003c/th\u003e\n\u003cth\u003e更新时机\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eGo WSL Manager\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ewslMgr.processes\u003c/code\u003e Map\u003c/td\u003e\n\u003ctd\u003e启动/停止/PID 更新\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eNode.js\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eactiveProcesses\u003c/code\u003e + \u003ccode\u003einstanceLinuxPids\u003c/code\u003e + \u003ccode\u003einstanceStatuses\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e启动/日志解析/对账\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003cp dir=\"auto\"\u003e两者通过 HTTP 通信，无一致性保证，可能出现状态不一致。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 明确单一事实来源。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e5.5 Linux PID 通过日志正则解析获取（P2）\u003c/h3\u003e\u003ca id=\"user-content-55-linux-pid-通过日志正则解析获取p2\" class=\"anchor\" aria-label=\"Permalink: 5.5 Linux PID 通过日志正则解析获取（P2）\" href=\"#55-linux-pid-通过日志正则解析获取p2\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e依赖日志轮询（2 秒间隔）+ 正则匹配提取 PID，Go 侧等待 5 秒，最坏 7 秒内 PID 未知。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 引擎启动脚本将 PID 写入 \u003ccode\u003e/tmp/{instanceId}.pid\u003c/code\u003e 文件。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e5.6 健康探测四层串行，最坏 32 秒/实例（P2）\u003c/h3\u003e\u003ca id=\"user-content-56-健康探测四层串行最坏-32-秒实例p2\" class=\"anchor\" aria-label=\"Permalink: 5.6 健康探测四层串行，最坏 32 秒/实例（P2）\" href=\"#56-健康探测四层串行最坏-32-秒实例p2\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"snippet-clipboard-content notranslate position-relative overflow-auto\" data-snippet-clipboard-copy-content=\"第0层: Go WSL Manager check (5s timeout)\n第1层: Linux PID kill -0 (5s timeout)\n第2层: WSL curl (12s timeout)\n第3层: Windows → WSL HTTP fetch (5s × 2)\"\u003e\u003cpre class=\"notranslate\"\u003e\u003ccode\u003e第0层: Go WSL Manager check (5s timeout)\n第1层: Linux PID kill -0 (5s timeout)\n第2层: WSL curl (12s timeout)\n第3层: Windows → WSL HTTP fetch (5s × 2)\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 第 1 层和第 2 层并行，去掉第 0 层。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e5.7 对账循环 20 秒间隔，崩溃发现延迟高（P2）\u003c/h3\u003e\u003ca id=\"user-content-57-对账循环-20-秒间隔崩溃发现延迟高p2\" class=\"anchor\" aria-label=\"Permalink: 5.7 对账循环 20 秒间隔，崩溃发现延迟高（P2）\" href=\"#57-对账循环-20-秒间隔崩溃发现延迟高p2\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e模型进程崩溃后最多 20 秒界面才从 running 变为 error，期间网关请求均 502。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 网关 ECONNREFUSED 时立即触发对该实例的对账。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e5.8 \u003ccode\u003ecmd.Wait()\u003c/code\u003e goroutine 泄漏（P2）\u003c/h3\u003e\u003ca id=\"user-content-58-cmdwait-goroutine-泄漏p2\" class=\"anchor\" aria-label=\"Permalink: 5.8 cmd.Wait() goroutine 泄漏（P2）\" href=\"#58-cmdwait-goroutine-泄漏p2\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e频繁启动→停止→启动同一实例，每次 \u003ccode\u003ecmd.Start()\u003c/code\u003e 产生新的 \u003ccode\u003eWait()\u003c/code\u003e goroutine，旧的在 \u003ccode\u003eProcess.Kill()\u003c/code\u003e 后才退出，持有 \u003ccode\u003ecmd\u003c/code\u003e 引用阻止 GC。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 用 \u003ccode\u003econtext.WithCancel\u003c/code\u003e 替代。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e5.9 孤儿进程扫描正则过于宽松（P2）\u003c/h3\u003e\u003ca id=\"user-content-59-孤儿进程扫描正则过于宽松p2\" class=\"anchor\" aria-label=\"Permalink: 5.9 孤儿进程扫描正则过于宽松（P2）\" href=\"#59-孤儿进程扫描正则过于宽松p2\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-ts notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"if (/vllm serve|vllm\\.entrypoints/.test(args)) engineType = \u0026quot;vllm\u0026quot;;\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003eif\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-pds\"\u003e\u003cspan class=\"pl-c1\"\u003e/\u003c/span\u003e\u003cspan class=\"pl-s\"\u003ev\u003c/span\u003e\u003cspan class=\"pl-s\"\u003el\u003c/span\u003e\u003cspan class=\"pl-s\"\u003el\u003c/span\u003e\u003cspan class=\"pl-s\"\u003em\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e \u003c/span\u003e\u003cspan class=\"pl-s\"\u003es\u003c/span\u003e\u003cspan class=\"pl-s\"\u003ee\u003c/span\u003e\u003cspan class=\"pl-s\"\u003er\u003c/span\u003e\u003cspan class=\"pl-s\"\u003ev\u003c/span\u003e\u003cspan class=\"pl-s\"\u003ee\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e|\u003c/span\u003e\u003cspan class=\"pl-s\"\u003ev\u003c/span\u003e\u003cspan class=\"pl-s\"\u003el\u003c/span\u003e\u003cspan class=\"pl-s\"\u003el\u003c/span\u003e\u003cspan class=\"pl-s\"\u003em\u003c/span\u003e\u003cspan class=\"pl-cce\"\u003e\\.\u003c/span\u003e\u003cspan class=\"pl-s\"\u003ee\u003c/span\u003e\u003cspan class=\"pl-s\"\u003en\u003c/span\u003e\u003cspan class=\"pl-s\"\u003et\u003c/span\u003e\u003cspan class=\"pl-s\"\u003er\u003c/span\u003e\u003cspan class=\"pl-s\"\u003ey\u003c/span\u003e\u003cspan class=\"pl-s\"\u003ep\u003c/span\u003e\u003cspan class=\"pl-s\"\u003eo\u003c/span\u003e\u003cspan class=\"pl-s\"\u003ei\u003c/span\u003e\u003cspan class=\"pl-s\"\u003en\u003c/span\u003e\u003cspan class=\"pl-s\"\u003et\u003c/span\u003e\u003cspan class=\"pl-s\"\u003es\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e/\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003etest\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eargs\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eengineType\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e=\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"vllm\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eps -eo pid=,etimes=args\u003c/code\u003e 输出可能匹配到非引擎进程。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e5.10 WSL2 Heartbeat 无条件运行（P2）\u003c/h3\u003e\u003ca id=\"user-content-510-wsl2-heartbeat-无条件运行p2\" class=\"anchor\" aria-label=\"Permalink: 5.10 WSL2 Heartbeat 无条件运行（P2）\" href=\"#510-wsl2-heartbeat-无条件运行p2\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e每 3 分钟执行 \u003ccode\u003ewsl.exe --exec true\u003c/code\u003e，无模型时也运行，WSL 关闭时自动唤醒 VM。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 仅在存在运行中实例时启用。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e5.11 \u003ccode\u003estopNodeServer()\u003c/code\u003e 直接 Kill（P2）\u003c/h3\u003e\u003ca id=\"user-content-511-stopnodeserver-直接-killp2\" class=\"anchor\" aria-label=\"Permalink: 5.11 stopNodeServer() 直接 Kill（P2）\" href=\"#511-stopnodeserver-直接-killp2\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-go notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"a.nodeCmd.Process.Kill()  // 直接 SIGKILL\"\u003e\u003cpre\u003e\u003cspan class=\"pl-s1\"\u003ea\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003enodeCmd\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eProcess\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eKill\u003c/span\u003e()  \u003cspan class=\"pl-c\"\u003e// 直接 SIGKILL\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eNode.js 无机会执行清理逻辑（录制落盘、索引刷新等）。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 先 SIGTERM，等待后 Kill。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e5.12 重启流程无事务语义（P2）\u003c/h3\u003e\u003ca id=\"user-content-512-重启流程无事务语义p2\" class=\"anchor\" aria-label=\"Permalink: 5.12 重启流程无事务语义（P2）\" href=\"#512-重启流程无事务语义p2\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003estopInstance\u003c/code\u003e 成功后 \u003ccode\u003estartInstance\u003c/code\u003e 失败，实例处于不一致状态。\u003c/p\u003e\n\u003chr\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e六、字体和颜色\u003c/h2\u003e\u003ca id=\"user-content-六字体和颜色\" class=\"anchor\" aria-label=\"Permalink: 六、字体和颜色\" href=\"#六字体和颜色\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003e相关文件：\u003ccode\u003evllm-launcher/frontend/src/index.css\u003c/code\u003e、\u003ccode\u003evllm-launcher/frontend/src/lib/theme.ts\u003c/code\u003e、\u003ccode\u003evllm-launcher/frontend/src/components/AssistantPanel.css\u003c/code\u003e、\u003ccode\u003evllm-launcher/frontend/tailwind.config.js\u003c/code\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e6.1 Google Fonts 在线依赖（P0）\u003c/h3\u003e\u003ca id=\"user-content-61-google-fonts-在线依赖p0\" class=\"anchor\" aria-label=\"Permalink: 6.1 Google Fonts 在线依赖（P0）\" href=\"#61-google-fonts-在线依赖p0\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-css notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@import url(\u0026quot;https://fonts.googleapis.com/css2?family=Chakra+Petch\u0026amp;family=IBM+Plex+Mono\u0026amp;family=Manrope\u0026amp;display=swap\u0026quot;);\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003e@import\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eurl\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"https://fonts.googleapis.com/css2?family=Chakra+Petch\u0026amp;family=IBM+Plex+Mono\u0026amp;family=Manrope\u0026amp;display=swap\"\u003c/span\u003e);\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e国内被墙，超时 10-30 秒，首屏渲染延迟。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 字体文件下载到本地，用 \u003ccode\u003e@font-face\u003c/code\u003e + \u003ccode\u003eembed\u003c/code\u003e 打包进应用。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e6.2 AssistantPanel px 字号不跟随缩放（P0）\u003c/h3\u003e\u003ca id=\"user-content-62-assistantpanel-px-字号不跟随缩放p0\" class=\"anchor\" aria-label=\"Permalink: 6.2 AssistantPanel px 字号不跟随缩放（P0）\" href=\"#62-assistantpanel-px-字号不跟随缩放p0\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eAssistantPanel.css 中 9 处 \u003ccode\u003epx\u003c/code\u003e 字号（\u003ccode\u003e13px\u003c/code\u003e、\u003ccode\u003e12px\u003c/code\u003e、\u003ccode\u003e11px\u003c/code\u003e），Ctrl+滚轮缩放根字号时助手面板 Markdown 内容不跟随。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e \u003ccode\u003epx\u003c/code\u003e → \u003ccode\u003erem\u003c/code\u003e（13px=0.929rem, 12px=0.857rem, 11px=0.786rem）。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e6.3 Modal 遮罩浅色失效（P0）\u003c/h3\u003e\u003ca id=\"user-content-63-modal-遮罩浅色失效p0\" class=\"anchor\" aria-label=\"Permalink: 6.3 Modal 遮罩浅色失效（P0）\" href=\"#63-modal-遮罩浅色失效p0\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003ebg-black/60\u003c/code\u003e 映射为 \u003ccode\u003evar(--app-inset-bg)\u003c/code\u003e，浅色主题下为 \u003ccode\u003ergba(255,255,255,0.60)\u003c/code\u003e，失去\"压暗\"效果。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 独立 \u003ccode\u003e.modal-overlay\u003c/code\u003e 类，浅色下用 \u003ccode\u003ebg-slate-900/30\u003c/code\u003e + \u003ccode\u003ebackdrop-blur-sm\u003c/code\u003e。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e6.4 浅色主题 150 行手动映射（P1）\u003c/h3\u003e\u003ca id=\"user-content-64-浅色主题-150-行手动映射p1\" class=\"anchor\" aria-label=\"Permalink: 6.4 浅色主题 150 行手动映射（P1）\" href=\"#64-浅色主题-150-行手动映射p1\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eindex.css 约 150 行 \u003ccode\u003ehtml[data-theme-mode=\"light\"] .text-xxx\u003c/code\u003e 手动覆盖，新增页面易遗漏。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e Tailwind 配置中扩展颜色 palette 或使用 CSS 变量 + \u003ccode\u003ecolor-mix()\u003c/code\u003e。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e6.5 SparkLineChart 硬编码 hex（P1）\u003c/h3\u003e\u003ca id=\"user-content-65-sparklinechart-硬编码-hexp1\" class=\"anchor\" aria-label=\"Permalink: 6.5 SparkLineChart 硬编码 hex（P1）\" href=\"#65-sparklinechart-硬编码-hexp1\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-ts notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"color: \u0026quot;#3AE3D6\u0026quot;  // 深色清晰，浅色隐形\ncolor: \u0026quot;#34D399\u0026quot;\ncolor: \u0026quot;#F59E0B\u0026quot;  // 浅色对比度不足\"\u003e\u003cpre\u003ecolor: \u003cspan class=\"pl-s\"\u003e\"#3AE3D6\"\u003c/span\u003e  \u003cspan class=\"pl-c\"\u003e// 深色清晰，浅色隐形\u003c/span\u003e\ncolor: \u003cspan class=\"pl-s\"\u003e\"#34D399\"\u003c/span\u003e\ncolor: \u003cspan class=\"pl-s\"\u003e\"#F59E0B\"\u003c/span\u003e  \u003cspan class=\"pl-c\"\u003e// 浅色对比度不足\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 用 Tailwind 颜色类或 CSS 变量。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e6.6 Tailwind 未自定义主题色（P1）\u003c/h3\u003e\u003ca id=\"user-content-66-tailwind-未自定义主题色p1\" class=\"anchor\" aria-label=\"Permalink: 6.6 Tailwind 未自定义主题色（P1）\" href=\"#66-tailwind-未自定义主题色p1\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003etailwind.config.js 完全使用默认配置，无法用 \u003ccode\u003ebg-card\u003c/code\u003e、\u003ccode\u003etext-primary\u003c/code\u003e 等语义化类名。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e6.7 主题切换闪烁（P1）\u003c/h3\u003e\u003ca id=\"user-content-67-主题切换闪烁p1\" class=\"anchor\" aria-label=\"Permalink: 6.7 主题切换闪烁（P1）\" href=\"#67-主题切换闪烁p1\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eCSS 变量先设置，\u003ccode\u003edata-theme-mode\u003c/code\u003e 后设置，中间出现半深色半浅色状态。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e建议：\u003c/strong\u003e 先设置 \u003ccode\u003edata-theme-mode\u003c/code\u003e，再设置 CSS 变量。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e6.8 字体选择稀少（P2）\u003c/h3\u003e\u003ca id=\"user-content-68-字体选择稀少p2\" class=\"anchor\" aria-label=\"Permalink: 6.8 字体选择稀少（P2）\" href=\"#68-字体选择稀少p2\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e仅 4 种字体（系统默认、微软雅黑、等线、黑体），无英文/代码友好字体，黑体不支持字重变化（合成粗体模糊）。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e6.9 等宽字体回退链不一致（P2）\u003c/h3\u003e\u003ca id=\"user-content-69-等宽字体回退链不一致p2\" class=\"anchor\" aria-label=\"Permalink: 6.9 等宽字体回退链不一致（P2）\" href=\"#69-等宽字体回退链不一致p2\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e终端面板用 \u003ccode\u003eIBM Plex Mono, monospace\u003c/code\u003e，代码块用 \u003ccode\u003eui-monospace, Cascadia Mono, Consolas, monospace\u003c/code\u003e，离线时字体不同。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e6.10 滚动条浅色对比度不足（P2）\u003c/h3\u003e\u003ca id=\"user-content-610-滚动条浅色对比度不足p2\" class=\"anchor\" aria-label=\"Permalink: 6.10 滚动条浅色对比度不足（P2）\" href=\"#610-滚动条浅色对比度不足p2\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e浅色下 \u003ccode\u003ergba(100, 116, 139, 0.45)\u003c/code\u003e 仍然偏淡。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e6.11 根元素文字颜色硬编码（P2）\u003c/h3\u003e\u003ca id=\"user-content-611-根元素文字颜色硬编码p2\" class=\"anchor\" aria-label=\"Permalink: 6.11 根元素文字颜色硬编码（P2）\" href=\"#611-根元素文字颜色硬编码p2\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-css notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\":root { color: #edf7ff; }  /* 固定值，非 CSS 变量 */\"\u003e\u003cpre\u003e\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eroot\u003c/span\u003e { \u003cspan class=\"pl-c1\"\u003ecolor\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e \u003cspan class=\"pl-pds\"\u003e\u003cspan class=\"pl-kos\"\u003e#\u003c/span\u003eedf7ff\u003c/span\u003e; }  \u003cspan class=\"pl-c\"\u003e/* 固定值，非 CSS 变量 */\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e新增主题时文字色可能不匹配背景。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e6.12 \u003ccode\u003eauto\u003c/code\u003e 主题 \u003ccode\u003emode\u003c/code\u003e 固定为 \u003ccode\u003e\"dark\"\u003c/code\u003e（P2）\u003c/h3\u003e\u003ca id=\"user-content-612-auto-主题-mode-固定为-darkp2\" class=\"anchor\" aria-label=\"Permalink: 6.12 auto 主题 mode 固定为 \u0026quot;dark\u0026quot;（P2）\" href=\"#612-auto-主题-mode-固定为-darkp2\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003edata-theme-mode\u003c/code\u003e 标记与实际渲染不一致，依赖 \u003ccode\u003eapplyThemeSettings\u003c/code\u003e 延迟修正，可能出现闪烁。\u003c/p\u003e\n\u003chr\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e全局优先级汇总\u003c/h2\u003e\u003ca id=\"user-content-全局优先级汇总\" class=\"anchor\" aria-label=\"Permalink: 全局优先级汇总\" href=\"#全局优先级汇总\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e优先级\u003c/th\u003e\n\u003cth\u003e问题数\u003c/th\u003e\n\u003cth\u003e涉及模块\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cstrong\u003eP0\u003c/strong\u003e\u003c/td\u003e\n\u003ctd\u003e8\u003c/td\u003e\n\u003ctd\u003e悬浮窗、主题、Gateway、加锁、进程、字体颜色\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cstrong\u003eP1\u003c/strong\u003e\u003c/td\u003e\n\u003ctd\u003e10\u003c/td\u003e\n\u003ctd\u003eGateway、加锁、进程、字体颜色\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cstrong\u003eP2\u003c/strong\u003e\u003c/td\u003e\n\u003ctd\u003e20+\u003c/td\u003e\n\u003ctd\u003e全模块\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003c/article\u003e","richTextTruncated":false,"renderedFileInfo":null,"symbols":{"timed_out":false,"not_analyzed":false,"symbols":[{"name":"vLLM Launcher 问题分析报告","fully_qualified_name":"vLLM Launcher 问题分析报告","kind":"section_1","ident_start":2,"ident_end":34,"extent_start":0,"extent_end":17431,"ident_utf16":{"start":{"line_number":0,"utf16_col":2},"end":{"line_number":0,"utf16_col":22}},"extent_utf16":{"start":{"line_number":0,"utf16_col":0},"end":{"line_number":494,"utf16_col":0}}},{"name":"目录","fully_qualified_name":"目录","kind":"section_2","ident_start":94,"ident_end":100,"extent_start":91,"extent_end":458,"ident_utf16":{"start":{"line_number":7,"utf16_col":3},"end":{"line_number":7,"utf16_col":5}},"extent_utf16":{"start":{"line_number":7,"utf16_col":0},"end":{"line_number":18,"utf16_col":0}}},{"name":"一、悬浮窗面板（FloatingBar）","fully_qualified_name":"一、悬浮窗面板（FloatingBar）","kind":"section_2","ident_start":461,"ident_end":499,"extent_start":458,"extent_end":2111,"ident_utf16":{"start":{"line_number":18,"utf16_col":3},"end":{"line_number":18,"utf16_col":23}},"extent_utf16":{"start":{"line_number":18,"utf16_col":0},"end":{"line_number":54,"utf16_col":0}}},{"name":"1.1 右侧 2×2 控制按钮区过于臃肿","fully_qualified_name":"1.1 右侧 2×2 控制按钮区过于臃肿","kind":"section_3","ident_start":579,"ident_end":622,"extent_start":575,"extent_end":809,"ident_utf16":{"start":{"line_number":22,"utf16_col":4},"end":{"line_number":22,"utf16_col":24}},"extent_utf16":{"start":{"line_number":22,"utf16_col":0},"end":{"line_number":26,"utf16_col":0}}},{"name":"1.2 信息密度过高，视觉层级混乱","fully_qualified_name":"1.2 信息密度过高，视觉层级混乱","kind":"section_3","ident_start":813,"ident_end":856,"extent_start":809,"extent_end":1094,"ident_utf16":{"start":{"line_number":26,"utf16_col":4},"end":{"line_number":26,"utf16_col":21}},"extent_utf16":{"start":{"line_number":26,"utf16_col":0},"end":{"line_number":30,"utf16_col":0}}},{"name":"1.3 第二行条件性出现导致布局跳动","fully_qualified_name":"1.3 第二行条件性出现导致布局跳动","kind":"section_3","ident_start":1098,"ident_end":1144,"extent_start":1094,"extent_end":1279,"ident_utf16":{"start":{"line_number":30,"utf16_col":4},"end":{"line_number":30,"utf16_col":22}},"extent_utf16":{"start":{"line_number":30,"utf16_col":0},"end":{"line_number":34,"utf16_col":0}}},{"name":"1.4 模型信息卡固定宽度，信息展示局促","fully_qualified_name":"1.4 模型信息卡固定宽度，信息展示局促","kind":"section_3","ident_start":1283,"ident_end":1335,"extent_start":1279,"extent_end":1428,"ident_utf16":{"start":{"line_number":34,"utf16_col":4},"end":{"line_number":34,"utf16_col":24}},"extent_utf16":{"start":{"line_number":34,"utf16_col":0},"end":{"line_number":38,"utf16_col":0}}},{"name":"1.5 动态背景动画过度","fully_qualified_name":"1.5 动态背景动画过度","kind":"section_3","ident_start":1432,"ident_end":1460,"extent_start":1428,"extent_end":1605,"ident_utf16":{"start":{"line_number":38,"utf16_col":4},"end":{"line_number":38,"utf16_col":16}},"extent_utf16":{"start":{"line_number":38,"utf16_col":0},"end":{"line_number":42,"utf16_col":0}}},{"name":"优化建议：精简 + 分层","fully_qualified_name":"优化建议：精简 + 分层","kind":"section_3","ident_start":1609,"ident_end":1639,"extent_start":1605,"extent_end":2111,"ident_utf16":{"start":{"line_number":42,"utf16_col":4},"end":{"line_number":42,"utf16_col":16}},"extent_utf16":{"start":{"line_number":42,"utf16_col":0},"end":{"line_number":54,"utf16_col":0}}},{"name":"二、主题样式","fully_qualified_name":"二、主题样式","kind":"section_2","ident_start":2114,"ident_end":2132,"extent_start":2111,"extent_end":4123,"ident_utf16":{"start":{"line_number":54,"utf16_col":3},"end":{"line_number":54,"utf16_col":9}},"extent_utf16":{"start":{"line_number":54,"utf16_col":0},"end":{"line_number":98,"utf16_col":0}}},{"name":"2.1 CSS 手动映射维护成本过高","fully_qualified_name":"2.1 CSS 手动映射维护成本过高","kind":"section_3","ident_start":2239,"ident_end":2277,"extent_start":2235,"extent_end":2500,"ident_utf16":{"start":{"line_number":58,"utf16_col":4},"end":{"line_number":58,"utf16_col":22}},"extent_utf16":{"start":{"line_number":58,"utf16_col":0},"end":{"line_number":62,"utf16_col":0}}},{"name":"2.2 遗漏的浅色主题覆盖","fully_qualified_name":"2.2 遗漏的浅色主题覆盖","kind":"section_3","ident_start":2504,"ident_end":2535,"extent_start":2500,"extent_end":3179,"ident_utf16":{"start":{"line_number":62,"utf16_col":4},"end":{"line_number":62,"utf16_col":17}},"extent_utf16":{"start":{"line_number":62,"utf16_col":0},"end":{"line_number":74,"utf16_col":0}}},{"name":"2.3 Modal 遮罩层浅色失效","fully_qualified_name":"2.3 Modal 遮罩层浅色失效","kind":"section_3","ident_start":3183,"ident_end":3214,"extent_start":3179,"extent_end":3493,"ident_utf16":{"start":{"line_number":74,"utf16_col":4},"end":{"line_number":74,"utf16_col":21}},"extent_utf16":{"start":{"line_number":74,"utf16_col":0},"end":{"line_number":80,"utf16_col":0}}},{"name":"2.4 AssistantPanel 代码块浅色对比度不足","fully_qualified_name":"2.4 AssistantPanel 代码块浅色对比度不足","kind":"section_3","ident_start":3497,"ident_end":3546,"extent_start":3493,"extent_end":3757,"ident_utf16":{"start":{"line_number":80,"utf16_col":4},"end":{"line_number":80,"utf16_col":33}},"extent_utf16":{"start":{"line_number":80,"utf16_col":0},"end":{"line_number":84,"utf16_col":0}}},{"name":"2.5 表面类名语义歧义","fully_qualified_name":"2.5 表面类名语义歧义","kind":"section_3","ident_start":3761,"ident_end":3789,"extent_start":3757,"extent_end":3941,"ident_utf16":{"start":{"line_number":84,"utf16_col":4},"end":{"line_number":84,"utf16_col":16}},"extent_utf16":{"start":{"line_number":84,"utf16_col":0},"end":{"line_number":92,"utf16_col":0}}},{"name":"2.6 Appearance 页面主题卡片预览对比度不足","fully_qualified_name":"2.6 Appearance 页面主题卡片预览对比度不足","kind":"section_3","ident_start":3945,"ident_end":3999,"extent_start":3941,"extent_end":4123,"ident_utf16":{"start":{"line_number":92,"utf16_col":4},"end":{"line_number":92,"utf16_col":32}},"extent_utf16":{"start":{"line_number":92,"utf16_col":0},"end":{"line_number":98,"utf16_col":0}}},{"name":"三、Gateway 网关处理","fully_qualified_name":"三、Gateway 网关处理","kind":"section_2","ident_start":4126,"ident_end":4152,"extent_start":4123,"extent_end":7721,"ident_utf16":{"start":{"line_number":98,"utf16_col":3},"end":{"line_number":98,"utf16_col":17}},"extent_utf16":{"start":{"line_number":98,"utf16_col":0},"end":{"line_number":201,"utf16_col":0}}},{"name":"3.1 请求体被重复 JSON.parse（P0 性能）","fully_qualified_name":"3.1 请求体被重复 JSON.parse（P0 性能）","kind":"section_3","ident_start":4390,"ident_end":4438,"extent_start":4386,"extent_end":5087,"ident_utf16":{"start":{"line_number":102,"utf16_col":4},"end":{"line_number":102,"utf16_col":32}},"extent_utf16":{"start":{"line_number":102,"utf16_col":0},"end":{"line_number":121,"utf16_col":0}}},{"name":"3.2 SSE `.tee()` 双份流处理（P0 性能）","fully_qualified_name":"3.2 SSE `.tee()` 双份流处理（P0 性能）","kind":"section_3","ident_start":5091,"ident_end":5138,"extent_start":5087,"extent_end":5413,"ident_utf16":{"start":{"line_number":121,"utf16_col":4},"end":{"line_number":121,"utf16_col":33}},"extent_utf16":{"start":{"line_number":121,"utf16_col":0},"end":{"line_number":131,"utf16_col":0}}},{"name":"3.3 路由匹配 O(n) 线性扫描","fully_qualified_name":"3.3 路由匹配 O(n) 线性扫描","kind":"section_3","ident_start":5417,"ident_end":5451,"extent_start":5413,"extent_end":5819,"ident_utf16":{"start":{"line_number":131,"utf16_col":4},"end":{"line_number":131,"utf16_col":22}},"extent_utf16":{"start":{"line_number":131,"utf16_col":0},"end":{"line_number":144,"utf16_col":0}}},{"name":"3.4 Token 估算代码重复","fully_qualified_name":"3.4 Token 估算代码重复","kind":"section_3","ident_start":5823,"ident_end":5851,"extent_start":5819,"extent_end":6102,"ident_utf16":{"start":{"line_number":144,"utf16_col":4},"end":{"line_number":144,"utf16_col":20}},"extent_utf16":{"start":{"line_number":144,"utf16_col":0},"end":{"line_number":154,"utf16_col":0}}},{"name":"3.5 gatewayLogger 和 gatewayRecorder 功能重叠","fully_qualified_name":"3.5 gatewayLogger 和 gatewayRecorder 功能重叠","kind":"section_3","ident_start":6106,"ident_end":6156,"extent_start":6102,"extent_end":6559,"ident_utf16":{"start":{"line_number":154,"utf16_col":4},"end":{"line_number":154,"utf16_col":44}},"extent_utf16":{"start":{"line_number":154,"utf16_col":0},"end":{"line_number":166,"utf16_col":0}}},{"name":"3.6 activeEntry 注册两次 + 类型断言不安全","fully_qualified_name":"3.6 activeEntry 注册两次 + 类型断言不安全","kind":"section_3","ident_start":6563,"ident_end":6615,"extent_start":6559,"extent_end":6891,"ident_utf16":{"start":{"line_number":166,"utf16_col":4},"end":{"line_number":166,"utf16_col":34}},"extent_utf16":{"start":{"line_number":166,"utf16_col":0},"end":{"line_number":177,"utf16_col":0}}},{"name":"3.7 Anthropic Gateway 兜底路由到第一个实例","fully_qualified_name":"3.7 Anthropic Gateway 兜底路由到第一个实例","kind":"section_3","ident_start":6895,"ident_end":6947,"extent_start":6891,"extent_end":7171,"ident_utf16":{"start":{"line_number":177,"utf16_col":4},"end":{"line_number":177,"utf16_col":36}},"extent_utf16":{"start":{"line_number":177,"utf16_col":0},"end":{"line_number":187,"utf16_col":0}}},{"name":"3.8 系统代理不走统一管线","fully_qualified_name":"3.8 系统代理不走统一管线","kind":"section_3","ident_start":7175,"ident_end":7209,"extent_start":7171,"extent_end":7383,"ident_utf16":{"start":{"line_number":187,"utf16_col":4},"end":{"line_number":187,"utf16_col":18}},"extent_utf16":{"start":{"line_number":187,"utf16_col":0},"end":{"line_number":191,"utf16_col":0}}},{"name":"3.9 非流式响应逻辑重复","fully_qualified_name":"3.9 非流式响应逻辑重复","kind":"section_3","ident_start":7387,"ident_end":7418,"extent_start":7383,"extent_end":7569,"ident_utf16":{"start":{"line_number":191,"utf16_col":4},"end":{"line_number":191,"utf16_col":17}},"extent_utf16":{"start":{"line_number":191,"utf16_col":0},"end":{"line_number":195,"utf16_col":0}}},{"name":"3.10 错误处理不精细","fully_qualified_name":"3.10 错误处理不精细","kind":"section_3","ident_start":7573,"ident_end":7599,"extent_start":7569,"extent_end":7721,"ident_utf16":{"start":{"line_number":195,"utf16_col":4},"end":{"line_number":195,"utf16_col":16}},"extent_utf16":{"start":{"line_number":195,"utf16_col":0},"end":{"line_number":201,"utf16_col":0}}},{"name":"四、模型实例加锁技术","fully_qualified_name":"四、模型实例加锁技术","kind":"section_2","ident_start":7724,"ident_end":7754,"extent_start":7721,"extent_end":10536,"ident_utf16":{"start":{"line_number":201,"utf16_col":3},"end":{"line_number":201,"utf16_col":13}},"extent_utf16":{"start":{"line_number":201,"utf16_col":0},"end":{"line_number":294,"utf16_col":0}}},{"name":"4.1 运行时热切换未受锁保护（P0 安全漏洞）","fully_qualified_name":"4.1 运行时热切换未受锁保护（P0 安全漏洞）","kind":"section_3","ident_start":7998,"ident_end":8056,"extent_start":7994,"extent_end":8256,"ident_utf16":{"start":{"line_number":205,"utf16_col":4},"end":{"line_number":205,"utf16_col":28}},"extent_utf16":{"start":{"line_number":205,"utf16_col":0},"end":{"line_number":209,"utf16_col":0}}},{"name":"4.2 实例启动/停止未受锁保护（P0 安全漏洞）","fully_qualified_name":"4.2 实例启动/停止未受锁保护（P0 安全漏洞）","kind":"section_3","ident_start":8260,"ident_end":8319,"extent_start":8256,"extent_end":8447,"ident_utf16":{"start":{"line_number":209,"utf16_col":4},"end":{"line_number":209,"utf16_col":29}},"extent_utf16":{"start":{"line_number":209,"utf16_col":0},"end":{"line_number":217,"utf16_col":0}}},{"name":"4.3 `isPresetLocked` 每次读盘（P1 性能）","fully_qualified_name":"4.3 `isPresetLocked` 每次读盘（P1 性能）","kind":"section_3","ident_start":8451,"ident_end":8499,"extent_start":8447,"extent_end":8820,"ident_utf16":{"start":{"line_number":217,"utf16_col":4},"end":{"line_number":217,"utf16_col":36}},"extent_utf16":{"start":{"line_number":217,"utf16_col":0},"end":{"line_number":230,"utf16_col":0}}},{"name":"4.4 锁检查与操作的 TOCTOU 窗口","fully_qualified_name":"4.4 锁检查与操作的 TOCTOU 窗口","kind":"section_3","ident_start":8824,"ident_end":8863,"extent_start":8820,"extent_end":9062,"ident_utf16":{"start":{"line_number":230,"utf16_col":4},"end":{"line_number":230,"utf16_col":25}},"extent_utf16":{"start":{"line_number":230,"utf16_col":0},"end":{"line_number":236,"utf16_col":0}}},{"name":"4.5 锁粒度单一（仅 boolean）","fully_qualified_name":"4.5 锁粒度单一（仅 boolean）","kind":"section_3","ident_start":9066,"ident_end":9102,"extent_start":9062,"extent_end":9390,"ident_utf16":{"start":{"line_number":236,"utf16_col":4},"end":{"line_number":236,"utf16_col":24}},"extent_utf16":{"start":{"line_number":236,"utf16_col":0},"end":{"line_number":255,"utf16_col":0}}},{"name":"4.6 锁状态变更无审计日志","fully_qualified_name":"4.6 锁状态变更无审计日志","kind":"section_3","ident_start":9394,"ident_end":9428,"extent_start":9390,"extent_end":9564,"ident_utf16":{"start":{"line_number":255,"utf16_col":4},"end":{"line_number":255,"utf16_col":18}},"extent_utf16":{"start":{"line_number":255,"utf16_col":0},"end":{"line_number":261,"utf16_col":0}}},{"name":"4.7 并发锁写入无保护","fully_qualified_name":"4.7 并发锁写入无保护","kind":"section_3","ident_start":9568,"ident_end":9596,"extent_start":9564,"extent_end":9787,"ident_utf16":{"start":{"line_number":261,"utf16_col":4},"end":{"line_number":261,"utf16_col":16}},"extent_utf16":{"start":{"line_number":261,"utf16_col":0},"end":{"line_number":267,"utf16_col":0}}},{"name":"4.8 删除路由中锁检查优先于活动状态检查","fully_qualified_name":"4.8 删除路由中锁检查优先于活动状态检查","kind":"section_3","ident_start":9791,"ident_end":9846,"extent_start":9787,"extent_end":10136,"ident_utf16":{"start":{"line_number":267,"utf16_col":4},"end":{"line_number":267,"utf16_col":25}},"extent_utf16":{"start":{"line_number":267,"utf16_col":0},"end":{"line_number":282,"utf16_col":0}}},{"name":"4.9 锁检查分散，无中间件","fully_qualified_name":"4.9 锁检查分散，无中间件","kind":"section_3","ident_start":10140,"ident_end":10174,"extent_start":10136,"extent_end":10337,"ident_utf16":{"start":{"line_number":282,"utf16_col":4},"end":{"line_number":282,"utf16_col":18}},"extent_utf16":{"start":{"line_number":282,"utf16_col":0},"end":{"line_number":288,"utf16_col":0}}},{"name":"4.10 锁继承关系未定义","fully_qualified_name":"4.10 锁继承关系未定义","kind":"section_3","ident_start":10341,"ident_end":10370,"extent_start":10337,"extent_end":10536,"ident_utf16":{"start":{"line_number":288,"utf16_col":4},"end":{"line_number":288,"utf16_col":17}},"extent_utf16":{"start":{"line_number":288,"utf16_col":0},"end":{"line_number":294,"utf16_col":0}}},{"name":"五、进程处理（Go 入口）","fully_qualified_name":"五、进程处理（Go 入口）","kind":"section_2","ident_start":10539,"ident_end":10572,"extent_start":10536,"extent_end":14183,"ident_utf16":{"start":{"line_number":294,"utf16_col":3},"end":{"line_number":294,"utf16_col":16}},"extent_utf16":{"start":{"line_number":294,"utf16_col":0},"end":{"line_number":409,"utf16_col":0}}},{"name":"5.1 `UnrefAllProcesses()` 空操作（P0 热退出不可靠）","fully_qualified_name":"5.1 `UnrefAllProcesses()` 空操作（P0 热退出不可靠）","kind":"section_3","ident_start":10796,"ident_end":10858,"extent_start":10792,"extent_end":11243,"ident_utf16":{"start":{"line_number":298,"utf16_col":4},"end":{"line_number":298,"utf16_col":44}},"extent_utf16":{"start":{"line_number":298,"utf16_col":0},"end":{"line_number":312,"utf16_col":0}}},{"name":"5.2 `handleStop` kill 与 delete 竞态（P0）","fully_qualified_name":"5.2 `handleStop` kill 与 delete 竞态（P0）","kind":"section_3","ident_start":11247,"ident_end":11294,"extent_start":11243,"extent_end":11653,"ident_utf16":{"start":{"line_number":312,"utf16_col":4},"end":{"line_number":312,"utf16_col":41}},"extent_utf16":{"start":{"line_number":312,"utf16_col":0},"end":{"line_number":324,"utf16_col":0}}},{"name":"5.3 Node.js 自动重启无上限（P1）","fully_qualified_name":"5.3 Node.js 自动重启无上限（P1）","kind":"section_3","ident_start":11657,"ident_end":11698,"extent_start":11653,"extent_end":11921,"ident_utf16":{"start":{"line_number":324,"utf16_col":4},"end":{"line_number":324,"utf16_col":27}},"extent_utf16":{"start":{"line_number":324,"utf16_col":0},"end":{"line_number":339,"utf16_col":0}}},{"name":"5.4 Go 与 Node.js 进程跟踪双重管理（P1）","fully_qualified_name":"5.4 Go 与 Node.js 进程跟踪双重管理（P1）","kind":"section_3","ident_start":11925,"ident_end":11976,"extent_start":11921,"extent_end":12344,"ident_utf16":{"start":{"line_number":339,"utf16_col":4},"end":{"line_number":339,"utf16_col":33}},"extent_utf16":{"start":{"line_number":339,"utf16_col":0},"end":{"line_number":350,"utf16_col":0}}},{"name":"5.5 Linux PID 通过日志正则解析获取（P2）","fully_qualified_name":"5.5 Linux PID 通过日志正则解析获取（P2）","kind":"section_3","ident_start":12348,"ident_end":12400,"extent_start":12344,"extent_end":12598,"ident_utf16":{"start":{"line_number":350,"utf16_col":4},"end":{"line_number":350,"utf16_col":32}},"extent_utf16":{"start":{"line_number":350,"utf16_col":0},"end":{"line_number":356,"utf16_col":0}}},{"name":"5.6 健康探测四层串行，最坏 32 秒/实例（P2）","fully_qualified_name":"5.6 健康探测四层串行，最坏 32 秒/实例（P2）","kind":"section_3","ident_start":12602,"ident_end":12661,"extent_start":12598,"extent_end":12897,"ident_utf16":{"start":{"line_number":356,"utf16_col":4},"end":{"line_number":356,"utf16_col":31}},"extent_utf16":{"start":{"line_number":356,"utf16_col":0},"end":{"line_number":367,"utf16_col":0}}},{"name":"5.7 对账循环 20 秒间隔，崩溃发现延迟高（P2）","fully_qualified_name":"5.7 对账循环 20 秒间隔，崩溃发现延迟高（P2）","kind":"section_3","ident_start":12901,"ident_end":12962,"extent_start":12897,"extent_end":13139,"ident_utf16":{"start":{"line_number":367,"utf16_col":4},"end":{"line_number":367,"utf16_col":31}},"extent_utf16":{"start":{"line_number":367,"utf16_col":0},"end":{"line_number":373,"utf16_col":0}}},{"name":"5.8 `cmd.Wait()` goroutine 泄漏（P2）","fully_qualified_name":"5.8 `cmd.Wait()` goroutine 泄漏（P2）","kind":"section_3","ident_start":13143,"ident_end":13184,"extent_start":13139,"extent_end":13411,"ident_utf16":{"start":{"line_number":373,"utf16_col":4},"end":{"line_number":373,"utf16_col":37}},"extent_utf16":{"start":{"line_number":373,"utf16_col":0},"end":{"line_number":379,"utf16_col":0}}},{"name":"5.9 孤儿进程扫描正则过于宽松（P2）","fully_qualified_name":"5.9 孤儿进程扫描正则过于宽松（P2）","kind":"section_3","ident_start":13415,"ident_end":13463,"extent_start":13411,"extent_end":13619,"ident_utf16":{"start":{"line_number":379,"utf16_col":4},"end":{"line_number":379,"utf16_col":24}},"extent_utf16":{"start":{"line_number":379,"utf16_col":0},"end":{"line_number":387,"utf16_col":0}}},{"name":"5.10 WSL2 Heartbeat 无条件运行（P2）","fully_qualified_name":"5.10 WSL2 Heartbeat 无条件运行（P2）","kind":"section_3","ident_start":13623,"ident_end":13666,"extent_start":13619,"extent_end":13823,"ident_utf16":{"start":{"line_number":387,"utf16_col":4},"end":{"line_number":387,"utf16_col":33}},"extent_utf16":{"start":{"line_number":387,"utf16_col":0},"end":{"line_number":393,"utf16_col":0}}},{"name":"5.11 `stopNodeServer()` 直接 Kill（P2）","fully_qualified_name":"5.11 `stopNodeServer()` 直接 Kill（P2）","kind":"section_3","ident_start":13827,"ident_end":13870,"extent_start":13823,"extent_end":14050,"ident_utf16":{"start":{"line_number":393,"utf16_col":4},"end":{"line_number":393,"utf16_col":39}},"extent_utf16":{"start":{"line_number":393,"utf16_col":0},"end":{"line_number":403,"utf16_col":0}}},{"name":"5.12 重启流程无事务语义（P2）","fully_qualified_name":"5.12 重启流程无事务语义（P2）","kind":"section_3","ident_start":14054,"ident_end":14094,"extent_start":14050,"extent_end":14183,"ident_utf16":{"start":{"line_number":403,"utf16_col":4},"end":{"line_number":403,"utf16_col":22}},"extent_utf16":{"start":{"line_number":403,"utf16_col":0},"end":{"line_number":409,"utf16_col":0}}},{"name":"六、字体和颜色","fully_qualified_name":"六、字体和颜色","kind":"section_2","ident_start":14186,"ident_end":14207,"extent_start":14183,"extent_end":17166,"ident_utf16":{"start":{"line_number":409,"utf16_col":3},"end":{"line_number":409,"utf16_col":10}},"extent_utf16":{"start":{"line_number":409,"utf16_col":0},"end":{"line_number":487,"utf16_col":0}}},{"name":"6.1 Google Fonts 在线依赖（P0）","fully_qualified_name":"6.1 Google Fonts 在线依赖（P0）","kind":"section_3","ident_start":14421,"ident_end":14458,"extent_start":14417,"extent_end":14739,"ident_utf16":{"start":{"line_number":413,"utf16_col":4},"end":{"line_number":413,"utf16_col":29}},"extent_utf16":{"start":{"line_number":413,"utf16_col":0},"end":{"line_number":423,"utf16_col":0}}},{"name":"6.2 AssistantPanel px 字号不跟随缩放（P0）","fully_qualified_name":"6.2 AssistantPanel px 字号不跟随缩放（P0）","kind":"section_3","ident_start":14743,"ident_end":14794,"extent_start":14739,"extent_end":15104,"ident_utf16":{"start":{"line_number":423,"utf16_col":4},"end":{"line_number":423,"utf16_col":37}},"extent_utf16":{"start":{"line_number":423,"utf16_col":0},"end":{"line_number":429,"utf16_col":0}}},{"name":"6.3 Modal 遮罩浅色失效（P0）","fully_qualified_name":"6.3 Modal 遮罩浅色失效（P0）","kind":"section_3","ident_start":15108,"ident_end":15144,"extent_start":15104,"extent_end":15365,"ident_utf16":{"start":{"line_number":429,"utf16_col":4},"end":{"line_number":429,"utf16_col":24}},"extent_utf16":{"start":{"line_number":429,"utf16_col":0},"end":{"line_number":435,"utf16_col":0}}},{"name":"6.4 浅色主题 150 行手动映射（P1）","fully_qualified_name":"6.4 浅色主题 150 行手动映射（P1）","kind":"section_3","ident_start":15369,"ident_end":15413,"extent_start":15365,"extent_end":15686,"ident_utf16":{"start":{"line_number":435,"utf16_col":4},"end":{"line_number":435,"utf16_col":26}},"extent_utf16":{"start":{"line_number":435,"utf16_col":0},"end":{"line_number":441,"utf16_col":0}}},{"name":"6.5 SparkLineChart 硬编码 hex（P1）","fully_qualified_name":"6.5 SparkLineChart 硬编码 hex（P1）","kind":"section_3","ident_start":15690,"ident_end":15730,"extent_start":15686,"extent_end":15915,"ident_utf16":{"start":{"line_number":441,"utf16_col":4},"end":{"line_number":441,"utf16_col":34}},"extent_utf16":{"start":{"line_number":441,"utf16_col":0},"end":{"line_number":451,"utf16_col":0}}},{"name":"6.6 Tailwind 未自定义主题色（P1）","fully_qualified_name":"6.6 Tailwind 未自定义主题色（P1）","kind":"section_3","ident_start":15919,"ident_end":15961,"extent_start":15915,"extent_end":16136,"ident_utf16":{"start":{"line_number":451,"utf16_col":4},"end":{"line_number":451,"utf16_col":28}},"extent_utf16":{"start":{"line_number":451,"utf16_col":0},"end":{"line_number":455,"utf16_col":0}}},{"name":"6.7 主题切换闪烁（P1）","fully_qualified_name":"6.7 主题切换闪烁（P1）","kind":"section_3","ident_start":16140,"ident_end":16170,"extent_start":16136,"extent_end":16334,"ident_utf16":{"start":{"line_number":455,"utf16_col":4},"end":{"line_number":455,"utf16_col":18}},"extent_utf16":{"start":{"line_number":455,"utf16_col":0},"end":{"line_number":461,"utf16_col":0}}},{"name":"6.8 字体选择稀少（P2）","fully_qualified_name":"6.8 字体选择稀少（P2）","kind":"section_3","ident_start":16338,"ident_end":16368,"extent_start":16334,"extent_end":16526,"ident_utf16":{"start":{"line_number":461,"utf16_col":4},"end":{"line_number":461,"utf16_col":18}},"extent_utf16":{"start":{"line_number":461,"utf16_col":0},"end":{"line_number":465,"utf16_col":0}}},{"name":"6.9 等宽字体回退链不一致（P2）","fully_qualified_name":"6.9 等宽字体回退链不一致（P2）","kind":"section_3","ident_start":16530,"ident_end":16572,"extent_start":16526,"extent_end":16711,"ident_utf16":{"start":{"line_number":465,"utf16_col":4},"end":{"line_number":465,"utf16_col":22}},"extent_utf16":{"start":{"line_number":465,"utf16_col":0},"end":{"line_number":469,"utf16_col":0}}},{"name":"6.10 滚动条浅色对比度不足（P2）","fully_qualified_name":"6.10 滚动条浅色对比度不足（P2）","kind":"section_3","ident_start":16715,"ident_end":16758,"extent_start":16711,"extent_end":16815,"ident_utf16":{"start":{"line_number":469,"utf16_col":4},"end":{"line_number":469,"utf16_col":23}},"extent_utf16":{"start":{"line_number":469,"utf16_col":0},"end":{"line_number":473,"utf16_col":0}}},{"name":"6.11 根元素文字颜色硬编码（P2）","fully_qualified_name":"6.11 根元素文字颜色硬编码（P2）","kind":"section_3","ident_start":16819,"ident_end":16862,"extent_start":16815,"extent_end":16986,"ident_utf16":{"start":{"line_number":473,"utf16_col":4},"end":{"line_number":473,"utf16_col":23}},"extent_utf16":{"start":{"line_number":473,"utf16_col":0},"end":{"line_number":481,"utf16_col":0}}},{"name":"6.12 `auto` 主题 `mode` 固定为 `\"dark\"`（P2）","fully_qualified_name":"6.12 `auto` 主题 `mode` 固定为 `\"dark\"`（P2）","kind":"section_3","ident_start":16990,"ident_end":17042,"extent_start":16986,"extent_end":17166,"ident_utf16":{"start":{"line_number":481,"utf16_col":4},"end":{"line_number":481,"utf16_col":42}},"extent_utf16":{"start":{"line_number":481,"utf16_col":0},"end":{"line_number":487,"utf16_col":0}}},{"name":"全局优先级汇总","fully_qualified_name":"全局优先级汇总","kind":"section_2","ident_start":17169,"ident_end":17190,"extent_start":17166,"extent_end":17431,"ident_utf16":{"start":{"line_number":487,"utf16_col":3},"end":{"line_number":487,"utf16_col":10}},"extent_utf16":{"start":{"line_number":487,"utf16_col":0},"end":{"line_number":494,"utf16_col":0}}}]}},"codeViewLayoutRoute":{"repo":{"id":1327765093,"defaultBranch":"main","name":"nova-studio","ownerLogin":"fuxingliang","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2026-08-08T13:13:11.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/37263150?v=4","public":true,"private":false,"isOrgOwned":false,"isArchived":false},"currentUser":null,"uploadToken":"Pm6yHnRvn4KHGQzTQ6jqyq0E5nHd0GzYYqBdB3MUW40G8JBZA6CisdR5AAq9pHbGkbqNBbArYx3NEETAXbsanQ","allShortcutsEnabled":false,"treeExpanded":true,"path":"BUG_ANALYSIS.md","symbolsExpanded":false,"refInfo":{"name":"main","listCacheKey":"v0:1787127723.0","canEdit":false,"currentOid":"c222dbf76b041bf84fe35417be1217e5f7ae561c"},"helpUrl":"https://docs.github.com","githubDevUrl":null},"codeViewFileTreeLayoutRoute":{"fileTree":{"":{"items":[{"name":"docs","path":"docs","contentType":"directory"},{"name":"finetune","path":"finetune","contentType":"directory"},{"name":"launcher","path":"launcher","contentType":"directory"},{"name":"scripts","path":"scripts","contentType":"directory"},{"name":"vllm-launcher","path":"vllm-launcher","contentType":"directory"},{"name":".gitignore","path":".gitignore","contentType":"file"},{"name":"BUG_ANALYSIS.md","path":"BUG_ANALYSIS.md","contentType":"file"},{"name":"LICENSE","path":"LICENSE","contentType":"file"},{"name":"README.md","path":"README.md","contentType":"file"},{"name":"README.zh-CN.md","path":"README.zh-CN.md","contentType":"file"},{"name":"SECURITY_AUDIT.md","path":"SECURITY_AUDIT.md","contentType":"file"},{"name":"fix-port-once.bat","path":"fix-port-once.bat","contentType":"file"},{"name":"shot1_overview.png","path":"shot1_overview.png","contentType":"file"},{"name":"shot2_params_panel.png","path":"shot2_params_panel.png","contentType":"file"},{"name":"shot3_llamacpp_gpu_section.png","path":"shot3_llamacpp_gpu_section.png","contentType":"file"}],"totalCount":15}},"fileTreeProcessingTime":14.270269,"foldersToFetch":[]},"codeViewBlobLayoutRoute":{"codeLineWrapEnabled":false,"refInfo":{"name":"main","listCacheKey":"v0:1787127723.0","canEdit":false,"refType":"branch","currentOid":"c222dbf76b041bf84fe35417be1217e5f7ae561c","canEditOnDefaultBranch":false,"fileExistsOnDefault":true},"path":"BUG_ANALYSIS.md","blob":{"copilotSWEAgentEnabled":false,"dependabotInfo":{"showConfigurationBanner":false,"configFilePath":null,"networkDependabotPath":"/fuxingliang/nova-studio/network/updates","dismissConfigurationNoticePath":"/settings/dismiss-notice/dependabot_configuration_notice","configurationNoticeDismissed":null},"displayName":"BUG_ANALYSIS.md","displayUrl":"https://github.com/fuxingliang/nova-studio/blob/main/BUG_ANALYSIS.md?raw=true","headerInfo":{"blobSize":"17 KB","deleteTooltip":"You must be signed in to make or propose changes","editTooltip":"You must be signed in to make or propose changes","ghDesktopPath":"https://desktop.github.com","isGitLfs":false,"onBranch":true,"shortPath":"77088d4","siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2Ffuxingliang%2Fnova-studio%2Fblob%2Fmain%2FBUG_ANALYSIS.md","isCSV":false,"isRichtext":true,"lineInfo":{"truncatedLoc":"494","truncatedSloc":"310"},"mode":"file"},"image":false,"isCodeownersFile":null,"isPlain":false,"isValidLegacyIssueTemplate":false,"isIssueTemplate":false,"isDiscussionTemplate":false,"language":"Markdown","languageID":222,"large":false,"planSupportInfo":{"repoIsFork":null,"repoOwnedByCurrentUser":null,"requestFullPath":"/fuxingliang/nova-studio/blob/main/BUG_ANALYSIS.md","showFreeOrgGatedFeatureMessage":null,"showPlanSupportBanner":null,"upgradeDataAttributes":null,"upgradePath":null},"publishBannersInfo":{"dismissActionNoticePath":"/settings/dismiss-notice/publish_action_from_dockerfile","releasePath":"/fuxingliang/nova-studio/releases/new?marketplace=true","showPublishActionBanner":false},"rawBlobUrl":"https://github.com/fuxingliang/nova-studio/raw/refs/heads/main/BUG_ANALYSIS.md","renderImageOrRaw":false,"shortPath":null,"symbolsEnabled":true,"tabSize":4,"topBannersInfo":{"overridingGlobalFundingFile":false,"globalPreferredFundingPath":null,"showInvalidCitationWarning":false,"citationHelpUrl":"https://docs.github.com/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-citation-files","actionsOnboardingTip":null},"truncated":false,"viewable":true,"workflowRedirectUrl":null},"copilotInfo":null,"copilotAccessAllowed":false,"copilotSpacesEnabled":false,"modelsAccessAllowed":false,"modelsRepoIntegrationEnabled":false,"isMarketplaceEnabled":true},"codeViewBlobLayoutRoute.StyledBlob":{"rawLines":["# vLLM Launcher 问题分析报告","","\u003e 生成日期：2026-08-08","\u003e 状态：待修复","","---","","## 目录","","- [一、悬浮窗面板（FloatingBar）](#一悬浮窗面板floatingbar)","- [二、主题样式](#二主题样式)","- [三、Gateway 网关处理](#三gateway-网关处理)","- [四、模型实例加锁技术](#四模型实例加锁技术)","- [五、进程处理（Go 入口）](#五进程处理go-入口)","- [六、字体和颜色](#六字体和颜色)","","---","","## 一、悬浮窗面板（FloatingBar）","","\u003e 相关文件：`vllm-launcher/frontend/src/components/FloatingBar.tsx`","","### 1.1 右侧 2×2 控制按钮区过于臃肿","","右侧占据 `grid-cols-2 gap-1` 的 2×2 网格（折叠/自动隐藏/收起/恢复），约 56px 宽度，4 个 12-14px 小图标辨识度差，\"折叠\"和\"收起\"语义易混淆。","","### 1.2 信息密度过高，视觉层级混乱","","第一行从左到右塞了 10+ 个元素（Logo → 停止 → 思考下拉框 → 阶段指示器 → TPS → Token → 预填充 → 进度条 → 耗时 → 实例切换器 → 运行计数 → 启动计数），无主次分组。","","### 1.3 第二行条件性出现导致布局跳动","","第二行（模型信息卡 + 压缩下拉框）在 `infoCollapsed` 或 `showStartup` 时整行消失，横栏内容上下跳动。","","### 1.4 模型信息卡固定宽度，信息展示局促","","模型名最多 130px，上下文进度条 52px，KV cache 两行小字，整体拥挤。","","### 1.5 动态背景动画过度","","推理时有扫描线、粒子流、波浪条、呼吸发光、能量脉冲等多层动画叠加，在 92px 高的横栏里分散注意力。","","### 优化建议：精简 + 分层","","| 优先级 | 内容 | 处理方式 |","|--------|------|----------|","| P0（常驻） | 阶段状态 + TPS + 模型名 | 永远可见 |","| P1（常驻） | 停止按钮 + 实例切换 | 永远可见 |","| P2（按需） | 思考模式 / 压缩模式 | 折叠到菜单或悬停展开 |","| P3（按需） | 上下文使用量 / KV Cache / 进度条 | 悬停或点击展开详情面板 |","| P4（低频） | 恢复窗口 / 自动隐藏 | 合并到右键菜单或单按钮 |","","---","","## 二、主题样式","","\u003e 相关文件：`vllm-launcher/frontend/src/index.css`、`vllm-launcher/frontend/src/lib/theme.ts`","","### 2.1 CSS 手动映射维护成本过高","","[index.css](file:///g:/vllm_5090D/vllm-launcher/frontend/src/index.css) 约 200 行手动 `html[data-theme-mode=\"light\"] .text-xxx { color: ... }` 映射，每新增颜色类需手动添加覆盖规则，容易遗漏。","","### 2.2 遗漏的浅色主题覆盖","","| 严重性 | 文件 | 类名 | 问题 |","|--------|------|------|------|","| 高 | index.css#L97 | `bg-[#050912]` | `.terminal-panel` 硬编码 hex |","| 高 | DiagnosticCards.tsx | `bg-black` | 纯黑背景浅色下不可见 |","| 高 | Downloads.tsx | `bg-slate-900/80` | CSS 仅覆盖 `/60` 和 `/70` 变体 |","| 高 | Finetune.tsx | `bg-slate-950` | 无透明度变体未覆盖 |","| 高 | FloatingBar.tsx | `bg-slate-950/95` | 提示框背景未覆盖 |","| 中 | InferenceTimeline.tsx | `bg-slate-800/90` | CSS 仅覆盖 `/40`、`/60`、`/80` |","| 中 | AssistantPanel.tsx | `border-slate-700`、`border-slate-600` | 边框浅色下可能消失 |","","### 2.3 Modal 遮罩层浅色失效","","多个组件使用 `bg-black/60` 遮罩，映射为 `var(--app-inset-bg)`，浅色主题下变为白色半透明，\"压暗\"效果完全失效。","","涉及文件：`AddModelDialog.tsx`、`ControlForm.tsx`、`ConfirmDialog.tsx`、`CreateInstanceDialog.tsx`、`ShutdownDialog.tsx`","","### 2.4 AssistantPanel 代码块浅色对比度不足","","[AssistantPanel.css](file:///g:/vllm_5090D/vllm-launcher/frontend/src/components/AssistantPanel.css) 代码块背景浅色下为 `#ffffff`，与面板背景无区分度；语法高亮无成熟浅色主题。","","### 2.5 表面类名语义歧义","","```css",".bg-white\\/5 { background-color: var(--app-card-bg, ...); }","```","","`bg-white/5` 暗示白色，实际随主题变化，降低类名可读性。","","### 2.6 Appearance 页面主题卡片预览对比度不足","","主题卡片预览区域（48px 高）在浅色主题下 `bg-white/5` 可能与浅色 deck 渐变对比度不足。","","---","","## 三、Gateway 网关处理","","\u003e 相关文件：`launcher/api/routes/gateway.ts`、`launcher/api/middleware/gatewayLogger.ts`、`launcher/api/services/gatewayRecorder.ts`、`launcher/api/services/contextCompressor.ts`、`launcher/api/routes/anthropicGateway.ts`","","### 3.1 请求体被重复 JSON.parse（P0 性能）","","`forwardGatewayRequest` 中请求体被解析至少 **8 次**：","","```","1. recordRequest → parseJsonSafely","2. truncateOversizedToolResults → JSON.parse","3. compressChatContext → JSON.parse","4. injectReasoningIntoBody → JSON.parse","5. injectStreamOptions → JSON.parse","6. 检测 isStream → JSON.parse","7. 获取 modelName → JSON.parse","8. shouldProcessReasoning → JSON.parse","```","","每次都是 `JSON.parse → 处理 → JSON.stringify → 再 parse`。大上下文请求（几十 KB ~ MB 级）明显延迟。","","**建议：** 入口处解析一次，传递 `parsedBody: Record\u003cstring, unknown\u003e` 对象，仅在转发前 stringify 一次。","","### 3.2 SSE `.tee()` 双份流处理（P0 性能）","","```typescript","const [upstreamForResponse, upstreamForLog] = upstreamReadableStream.tee();","```","","每个 byte 被处理两次（日志 + 响应），高 TPS 下翻倍 CPU 和内存。","","**建议：** 去掉 `.tee()`，将日志采集合并到主处理管线，单遍处理。","","### 3.3 路由匹配 O(n) 线性扫描","","```typescript","function findGatewayRouteByModel(modelName) {","  for (const status of getInstanceStatuses()) {  // O(n)","    const aliases = getGatewayAliases(status).map(...);  // 每次都重新生成","    if (aliases.includes(normalized)) { ... }","  }","}","```","","**建议：** 维护 `Map\u003cmodelAlias, GatewayRouteMatch\u003e` 路由表，实例启停时更新，查找 O(1)。","","### 3.4 Token 估算代码重复","","`estimateTokensFromText` 在两个文件中各实现一遍：","- `gateway.ts` 第 588 行","- `contextCompressor.ts` 第 49 行","","代码完全相同，维护两份容易不一致。","","**建议：** 提取到独立的 `tokenEstimator.ts` 工具模块。","","### 3.5 gatewayLogger 和 gatewayRecorder 功能重叠","","| | gatewayLogger | gatewayRecorder |","|---|---|---|","| 存储 | 内存数组（最多 50 条） | 磁盘 JSONL（最多 2GB） |","| 内容 | 请求头 + 截断 body + SSE preview | 完整 rawBody + 响应指标 |","| 用途 | 调试推理过程 | 分析 KV Cache / 客户端行为 |","","两者各自独立采集相同数据（model、messages、usage 等）。","","**建议：** 合并为单一录制管线。","","### 3.6 activeEntry 注册两次 + 类型断言不安全","","```typescript","// 第 819 行（回调内）","registerActiveUpstreamRequest(route.instanceId, activeEntry);","// 第 1035 行（回调外）","registerActiveUpstreamRequest(route.instanceId, activeEntry);","```","","**建议：** 只在 `http.request()` 返回后立即注册一次。","","### 3.7 Anthropic Gateway 兜底路由到第一个实例","","```typescript","const targetModel = matched?.modelId ?? instances[0]?.modelId;","```","","匹配失败时静默回退到第一个实例，可能路由到错误模型。","","**建议：** 返回明确 404 或按能力智能路由。","","### 3.8 系统代理不走统一管线","","系统代理劫持后走独立的 `forwardToGateway` 函数，不经过 `forwardGatewayRequest`，导致上下文压缩、推理处理等功能对代理路径不生效。","","### 3.9 非流式响应逻辑重复","","`reasoningConfig.enabled` 和 `!enabled` 两条路径都调用了 `captureInferenceMetrics`、`recorderSession?.captureUsage` 等，逻辑重复。","","### 3.10 错误处理不精细","","所有上游问题（ECONNREFUSED、ETIMEDOUT、引擎 5xx）都返回 502，客户端无法区分错误类型。","","---","","## 四、模型实例加锁技术","","\u003e 相关文件：`launcher/api/services/instanceManager.ts`、`launcher/api/services/presetStore.ts`、`launcher/api/services/cardMeta.ts`、`launcher/api/routes/instances.ts`、`launcher/api/routes/presets.ts`、`launcher/api/types.ts`","","### 4.1 运行时热切换未受锁保护（P0 安全漏洞）","","`PATCH /api/instances/:id/runtime/settings`（instances.ts 第 275 行）没有锁检查，可修改 reasoning/temperature/topP/stop/maxTokens/compression——这些正是锁要保护的参数。","","### 4.2 实例启动/停止未受锁保护（P0 安全漏洞）","","```typescript","// 无锁检查","router.post(\"/api/instances/:id/stop\", ...)","router.post(\"/api/instances/:id/restart\", ...)","```","","### 4.3 `isPresetLocked` 每次读盘（P1 性能）","","```typescript","export async function isPresetLocked(id: string): Promise\u003cboolean\u003e {","  const data = await readPresets();  // ← 磁盘 IO","  return data.presets.find(...)?.meta?.locked === true;","}","```","","而 `isInstanceLocked` 是纯内存操作。","","**建议：** 预设数据缓存到内存，锁检查走内存路径。","","### 4.4 锁检查与操作的 TOCTOU 窗口","","前端先检查锁再执行保存，存在竞态窗口。后端虽有最终拦截，但两套错误提示不一致。","","**建议：** 前端去掉锁检查，完全依赖后端 403 统一处理。","","### 4.5 锁粒度单一（仅 boolean）","","```typescript","export type CardMeta = {","  locked: boolean;  // 要么全锁要么全不锁","  // ...","};","```","","**建议：** 扩展为细粒度策略：","","```typescript","export type LockPolicy = {","  preventDelete: boolean;","  preventConfigChange: boolean;","  preventLifecycle: boolean;","};","```","","### 4.6 锁状态变更无审计日志","","`updateCardMeta` 直接修改内存 + 落盘，无 `createInstanceLog` 调用。","","**建议：** 锁状态变更时写实例日志。","","### 4.7 并发锁写入无保护","","多个请求同时修改同一实例的 meta 和 config 时，锁检查和修改分属不同异步操作，中间可能插入其他请求。","","**建议：** per-instance 串行化队列。","","### 4.8 删除路由中锁检查优先于活动状态检查","","```typescript","if (isInstanceLocked(instanceId)) {  // 先检查锁 → 403","  ...","}","if (status.phase === \"running\" || ...) {  // 再检查活动 → 409","  ...","}","```","","运行中且加锁的实例返回 403 而非 409，用户困惑。","","**建议：** 先检查活动状态，再检查锁。","","### 4.9 锁检查分散，无中间件","","`isPresetLocked` 检查分散在 `presets.ts` 多处，`isInstanceLocked` 同理，新增路由时容易遗漏。","","**建议：** 提取为 Express 中间件。","","### 4.10 锁继承关系未定义","","实例从预设创建时 `freshInstanceMeta` 总是重置 `locked: false`，预设加锁后创建的实例默认未加锁，行为合理但无文档说明。","","---","","## 五、进程处理（Go 入口）","","\u003e 相关文件：`vllm-launcher/main.go`、`launcher/api/services/instanceLifecycle.ts`、`launcher/api/services/instanceManager.ts`、`launcher/api/services/instanceRegistry.ts`、`launcher/api/services/wslProbe.ts`","","### 5.1 `UnrefAllProcesses()` 空操作（P0 热退出不可靠）","","```go","func (m *WslManager) UnrefAllProcesses() {","    m.mu.Lock()","    for id, proc := range m.processes {","        log.Printf(\"[WSL-MGR] Detaching instance %s\", id, proc.Pid)","    }","    m.mu.Unlock()","}","```","","只打日志，没有设置 `proc.Detached = true` 或释放 `proc.Cmd`。Go 进程退出时未 detached 的子进程会被级联杀死，热退出实际上可能杀掉模型。","","### 5.2 `handleStop` kill 与 delete 竞态（P0）","","```go","go func(pid int) {","    wslCommand(\"bash\", \"-c\", fmt.Sprintf(\"kill %d ...\", pid)).Run()","}(proc.LinuxPid)","delete(m.processes, req.InstanceID)  // 立即删除","json.NewEncoder(w).Encode(StartResponse{Success: true})  // 立即返回","```","","Kill 异步执行，Map 立即删除，响应立即返回。此时进程可能还在运行，端口仍被占用。","","### 5.3 Node.js 自动重启无上限（P1）","","```go","restartCount := 0","for {","    cmd.Wait()","    restartCount++","    // 无上限，无限重启","}","```","","`server.cjs` 启动错误时无限重启，每秒 2 次。","","**建议：** 添加上限（10 次）或退避策略。","","### 5.4 Go 与 Node.js 进程跟踪双重管理（P1）","","| 跟踪方 | 存储 | 更新时机 |","|--------|------|----------|","| Go WSL Manager | `wslMgr.processes` Map | 启动/停止/PID 更新 |","| Node.js | `activeProcesses` + `instanceLinuxPids` + `instanceStatuses` | 启动/日志解析/对账 |","","两者通过 HTTP 通信，无一致性保证，可能出现状态不一致。","","**建议：** 明确单一事实来源。","","### 5.5 Linux PID 通过日志正则解析获取（P2）","","依赖日志轮询（2 秒间隔）+ 正则匹配提取 PID，Go 侧等待 5 秒，最坏 7 秒内 PID 未知。","","**建议：** 引擎启动脚本将 PID 写入 `/tmp/{instanceId}.pid` 文件。","","### 5.6 健康探测四层串行，最坏 32 秒/实例（P2）","","```","第0层: Go WSL Manager check (5s timeout)","第1层: Linux PID kill -0 (5s timeout)","第2层: WSL curl (12s timeout)","第3层: Windows → WSL HTTP fetch (5s × 2)","```","","**建议：** 第 1 层和第 2 层并行，去掉第 0 层。","","### 5.7 对账循环 20 秒间隔，崩溃发现延迟高（P2）","","模型进程崩溃后最多 20 秒界面才从 running 变为 error，期间网关请求均 502。","","**建议：** 网关 ECONNREFUSED 时立即触发对该实例的对账。","","### 5.8 `cmd.Wait()` goroutine 泄漏（P2）","","频繁启动→停止→启动同一实例，每次 `cmd.Start()` 产生新的 `Wait()` goroutine，旧的在 `Process.Kill()` 后才退出，持有 `cmd` 引用阻止 GC。","","**建议：** 用 `context.WithCancel` 替代。","","### 5.9 孤儿进程扫描正则过于宽松（P2）","","```typescript","if (/vllm serve|vllm\\.entrypoints/.test(args)) engineType = \"vllm\";","```","","`ps -eo pid=,etimes=args` 输出可能匹配到非引擎进程。","","### 5.10 WSL2 Heartbeat 无条件运行（P2）","","每 3 分钟执行 `wsl.exe --exec true`，无模型时也运行，WSL 关闭时自动唤醒 VM。","","**建议：** 仅在存在运行中实例时启用。","","### 5.11 `stopNodeServer()` 直接 Kill（P2）","","```go","a.nodeCmd.Process.Kill()  // 直接 SIGKILL","```","","Node.js 无机会执行清理逻辑（录制落盘、索引刷新等）。","","**建议：** 先 SIGTERM，等待后 Kill。","","### 5.12 重启流程无事务语义（P2）","","`stopInstance` 成功后 `startInstance` 失败，实例处于不一致状态。","","---","","## 六、字体和颜色","","\u003e 相关文件：`vllm-launcher/frontend/src/index.css`、`vllm-launcher/frontend/src/lib/theme.ts`、`vllm-launcher/frontend/src/components/AssistantPanel.css`、`vllm-launcher/frontend/tailwind.config.js`","","### 6.1 Google Fonts 在线依赖（P0）","","```css","@import url(\"https://fonts.googleapis.com/css2?family=Chakra+Petch\u0026family=IBM+Plex+Mono\u0026family=Manrope\u0026display=swap\");","```","","国内被墙，超时 10-30 秒，首屏渲染延迟。","","**建议：** 字体文件下载到本地，用 `@font-face` + `embed` 打包进应用。","","### 6.2 AssistantPanel px 字号不跟随缩放（P0）","","[AssistantPanel.css](file:///g:/vllm_5090D/vllm-launcher/frontend/src/components/AssistantPanel.css) 中 9 处 `px` 字号（`13px`、`12px`、`11px`），Ctrl+滚轮缩放根字号时助手面板 Markdown 内容不跟随。","","**建议：** `px` → `rem`（13px=0.929rem, 12px=0.857rem, 11px=0.786rem）。","","### 6.3 Modal 遮罩浅色失效（P0）","","`bg-black/60` 映射为 `var(--app-inset-bg)`，浅色主题下为 `rgba(255,255,255,0.60)`，失去\"压暗\"效果。","","**建议：** 独立 `.modal-overlay` 类，浅色下用 `bg-slate-900/30` + `backdrop-blur-sm`。","","### 6.4 浅色主题 150 行手动映射（P1）","","[index.css](file:///g:/vllm_5090D/vllm-launcher/frontend/src/index.css#L247-L392) 约 150 行 `html[data-theme-mode=\"light\"] .text-xxx` 手动覆盖，新增页面易遗漏。","","**建议：** Tailwind 配置中扩展颜色 palette 或使用 CSS 变量 + `color-mix()`。","","### 6.5 SparkLineChart 硬编码 hex（P1）","","```typescript","color: \"#3AE3D6\"  // 深色清晰，浅色隐形","color: \"#34D399\"","color: \"#F59E0B\"  // 浅色对比度不足","```","","**建议：** 用 Tailwind 颜色类或 CSS 变量。","","### 6.6 Tailwind 未自定义主题色（P1）","","[tailwind.config.js](file:///g:/vllm_5090D/vllm-launcher/frontend/tailwind.config.js) 完全使用默认配置，无法用 `bg-card`、`text-primary` 等语义化类名。","","### 6.7 主题切换闪烁（P1）","","CSS 变量先设置，`data-theme-mode` 后设置，中间出现半深色半浅色状态。","","**建议：** 先设置 `data-theme-mode`，再设置 CSS 变量。","","### 6.8 字体选择稀少（P2）","","仅 4 种字体（系统默认、微软雅黑、等线、黑体），无英文/代码友好字体，黑体不支持字重变化（合成粗体模糊）。","","### 6.9 等宽字体回退链不一致（P2）","","终端面板用 `IBM Plex Mono, monospace`，代码块用 `ui-monospace, Cascadia Mono, Consolas, monospace`，离线时字体不同。","","### 6.10 滚动条浅色对比度不足（P2）","","浅色下 `rgba(100, 116, 139, 0.45)` 仍然偏淡。","","### 6.11 根元素文字颜色硬编码（P2）","","```css",":root { color: #edf7ff; }  /* 固定值，非 CSS 变量 */","```","","新增主题时文字色可能不匹配背景。","","### 6.12 `auto` 主题 `mode` 固定为 `\"dark\"`（P2）","","`data-theme-mode` 标记与实际渲染不一致，依赖 `applyThemeSettings` 延迟修正，可能出现闪烁。","","---","","## 全局优先级汇总","","| 优先级 | 问题数 | 涉及模块 |","|--------|--------|----------|","| **P0** | 8 | 悬浮窗、主题、Gateway、加锁、进程、字体颜色 |","| **P1** | 10 | Gateway、加锁、进程、字体颜色 |","| **P2** | 20+ | 全模块 |"],"stylingDirectives":[[[0,22,"pl-mh"],[2,22,"pl-en"]],[],[[0,17,"pl-ent"],[0,2,"pl-ent"]],[[0,8,"pl-ent"],[0,2,"pl-ent"]],[[0,0,"pl-ent"]],[[0,3,"pl-ms"]],[],[[0,5,"pl-mh"],[3,5,"pl-en"]],[],[[0,1,"pl-v"],[2,3,"pl-s"],[23,24,"pl-s"],[24,25,"pl-s"],[25,43,"pl-corl"],[43,44,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[9,10,"pl-s"],[10,11,"pl-s"],[11,17,"pl-corl"],[17,18,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[17,18,"pl-s"],[18,19,"pl-s"],[19,33,"pl-corl"],[33,34,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[13,14,"pl-s"],[14,15,"pl-s"],[15,25,"pl-corl"],[25,26,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[16,17,"pl-s"],[17,18,"pl-s"],[18,29,"pl-corl"],[29,30,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[10,11,"pl-s"],[11,12,"pl-s"],[12,19,"pl-corl"],[19,20,"pl-s"]],[],[[0,3,"pl-ms"]],[],[[0,23,"pl-mh"],[3,23,"pl-en"]],[],[[0,62,"pl-ent"],[0,2,"pl-ent"],[7,8,"pl-s"],[8,61,"pl-c1"],[61,62,"pl-s"]],[[0,0,"pl-ent"]],[[0,24,"pl-mh"],[4,24,"pl-en"]],[],[[5,6,"pl-s"],[6,23,"pl-c1"],[23,24,"pl-s"]],[],[[0,21,"pl-mh"],[4,21,"pl-en"]],[],[],[],[[0,22,"pl-mh"],[4,22,"pl-en"]],[],[[20,21,"pl-s"],[21,34,"pl-c1"],[34,35,"pl-s"],[38,39,"pl-s"],[39,50,"pl-c1"],[50,51,"pl-s"]],[],[[0,24,"pl-mh"],[4,24,"pl-en"]],[],[],[],[[0,16,"pl-mh"],[4,16,"pl-en"]],[],[],[],[[0,16,"pl-mh"],[4,16,"pl-en"]],[],[[0,1,"pl-ml"],[6,7,"pl-ml"],[11,12,"pl-ml"],[18,19,"pl-ml"]],[[0,1,"pl-ml"],[9,10,"pl-ml"],[16,17,"pl-ml"],[27,28,"pl-ml"]],[[0,1,"pl-ml"],[9,10,"pl-ml"],[28,29,"pl-ml"],[35,36,"pl-ml"]],[[0,1,"pl-ml"],[9,10,"pl-ml"],[23,24,"pl-ml"],[30,31,"pl-ml"]],[[0,1,"pl-ml"],[9,10,"pl-ml"],[23,24,"pl-ml"],[36,37,"pl-ml"]],[[0,1,"pl-ml"],[9,10,"pl-ml"],[35,36,"pl-ml"],[49,50,"pl-ml"]],[[0,1,"pl-ml"],[9,10,"pl-ml"],[23,24,"pl-ml"],[37,38,"pl-ml"]],[],[[0,3,"pl-ms"]],[],[[0,9,"pl-mh"],[3,9,"pl-en"]],[],[[0,87,"pl-ent"],[0,2,"pl-ent"],[7,8,"pl-s"],[8,44,"pl-c1"],[44,45,"pl-s"],[46,47,"pl-s"],[47,86,"pl-c1"],[86,87,"pl-s"]],[[0,0,"pl-ent"]],[[0,22,"pl-mh"],[4,22,"pl-en"]],[],[[0,1,"pl-s"],[10,11,"pl-s"],[11,12,"pl-s"],[12,70,"pl-corl"],[70,71,"pl-s"],[82,83,"pl-s"],[83,137,"pl-c1"],[137,138,"pl-s"]],[],[[0,17,"pl-mh"],[4,17,"pl-en"]],[],[[0,1,"pl-ml"],[6,7,"pl-ml"],[11,12,"pl-ml"],[16,17,"pl-ml"],[21,22,"pl-ml"]],[[0,1,"pl-ml"],[9,10,"pl-ml"],[16,17,"pl-ml"],[23,24,"pl-ml"],[30,31,"pl-ml"]],[[0,1,"pl-ml"],[4,5,"pl-ml"],[20,21,"pl-ml"],[22,23,"pl-s"],[23,35,"pl-c1"],[35,36,"pl-s"],[37,38,"pl-ml"],[39,40,"pl-s"],[40,55,"pl-c1"],[55,56,"pl-s"],[65,66,"pl-ml"]],[[0,1,"pl-ml"],[4,5,"pl-ml"],[26,27,"pl-ml"],[28,29,"pl-s"],[29,37,"pl-c1"],[37,38,"pl-s"],[39,40,"pl-ml"],[52,53,"pl-ml"]],[[0,1,"pl-ml"],[4,5,"pl-ml"],[20,21,"pl-ml"],[22,23,"pl-s"],[23,38,"pl-c1"],[38,39,"pl-s"],[40,41,"pl-ml"],[50,51,"pl-s"],[51,54,"pl-c1"],[54,55,"pl-s"],[58,59,"pl-s"],[59,62,"pl-c1"],[62,63,"pl-s"],[67,68,"pl-ml"]],[[0,1,"pl-ml"],[4,5,"pl-ml"],[19,20,"pl-ml"],[21,22,"pl-s"],[22,34,"pl-c1"],[34,35,"pl-s"],[36,37,"pl-ml"],[48,49,"pl-ml"]],[[0,1,"pl-ml"],[4,5,"pl-ml"],[22,23,"pl-ml"],[24,25,"pl-s"],[25,40,"pl-c1"],[40,41,"pl-s"],[42,43,"pl-ml"],[53,54,"pl-ml"]],[[0,1,"pl-ml"],[4,5,"pl-ml"],[28,29,"pl-ml"],[30,31,"pl-s"],[31,46,"pl-c1"],[46,47,"pl-s"],[48,49,"pl-ml"],[58,59,"pl-s"],[59,62,"pl-c1"],[62,63,"pl-s"],[64,65,"pl-s"],[65,68,"pl-c1"],[68,69,"pl-s"],[70,71,"pl-s"],[71,74,"pl-c1"],[74,75,"pl-s"],[76,77,"pl-ml"]],[[0,1,"pl-ml"],[4,5,"pl-ml"],[25,26,"pl-ml"],[27,28,"pl-s"],[28,44,"pl-c1"],[44,45,"pl-s"],[46,47,"pl-s"],[47,63,"pl-c1"],[63,64,"pl-s"],[65,66,"pl-ml"],[77,78,"pl-ml"]],[],[[0,21,"pl-mh"],[4,21,"pl-en"]],[],[[7,8,"pl-s"],[8,19,"pl-c1"],[19,20,"pl-s"],[28,29,"pl-s"],[29,48,"pl-c1"],[48,49,"pl-s"]],[],[[5,6,"pl-s"],[6,24,"pl-c1"],[24,25,"pl-s"],[26,27,"pl-s"],[27,42,"pl-c1"],[42,43,"pl-s"],[44,45,"pl-s"],[45,62,"pl-c1"],[62,63,"pl-s"],[64,65,"pl-s"],[65,89,"pl-c1"],[89,90,"pl-s"],[91,92,"pl-s"],[92,110,"pl-c1"],[110,111,"pl-s"]],[],[[0,33,"pl-mh"],[4,33,"pl-en"]],[],[[0,1,"pl-s"],[19,20,"pl-s"],[20,21,"pl-s"],[21,99,"pl-corl"],[99,100,"pl-s"],[111,112,"pl-s"],[112,119,"pl-c1"],[119,120,"pl-s"]],[],[[0,16,"pl-mh"],[4,16,"pl-en"]],[],[[0,3,"pl-s"],[3,6,"pl-en"]],[[0,12,"pl-e"],[9,11,"pl-cce"],[15,31,"pl-c1"],[15,31,"pl-c1"],[33,36,"pl-c1"],[37,50,"pl-v"]],[[0,3,"pl-s"]],[],[[0,1,"pl-s"],[1,11,"pl-c1"],[11,12,"pl-s"]],[],[[0,32,"pl-mh"],[4,32,"pl-en"]],[],[[23,24,"pl-s"],[24,34,"pl-c1"],[34,35,"pl-s"]],[],[[0,3,"pl-ms"]],[],[[0,17,"pl-mh"],[3,17,"pl-en"]],[],[[0,212,"pl-ent"],[0,2,"pl-ent"],[7,8,"pl-s"],[8,38,"pl-c1"],[38,39,"pl-s"],[40,41,"pl-s"],[41,81,"pl-c1"],[81,82,"pl-s"],[83,84,"pl-s"],[84,124,"pl-c1"],[124,125,"pl-s"],[126,127,"pl-s"],[127,169,"pl-c1"],[169,170,"pl-s"],[171,172,"pl-s"],[172,211,"pl-c1"],[211,212,"pl-s"]],[[0,0,"pl-ent"]],[[0,32,"pl-mh"],[4,32,"pl-en"]],[],[[0,1,"pl-s"],[1,22,"pl-c1"],[22,23,"pl-s"],[34,36,"pl-s"],[39,41,"pl-s"]],[],[[0,3,"pl-s"],[3,3,"pl-c1"]],[[0,34,"pl-c1"]],[[0,44,"pl-c1"]],[[0,35,"pl-c1"]],[[0,39,"pl-c1"]],[[0,35,"pl-c1"]],[[0,27,"pl-c1"]],[[0,28,"pl-c1"]],[[0,38,"pl-c1"]],[[0,0,"pl-c1"],[0,3,"pl-s"]],[],[[5,6,"pl-s"],[6,48,"pl-c1"],[48,49,"pl-s"]],[],[[0,2,"pl-s"],[5,7,"pl-s"],[19,20,"pl-s"],[20,55,"pl-c1"],[55,56,"pl-s"]],[],[[0,33,"pl-mh"],[4,33,"pl-en"],[12,13,"pl-s"],[13,19,"pl-c1"],[19,20,"pl-s"]],[],[[0,3,"pl-s"],[3,13,"pl-en"]],[[0,5,"pl-k"],[0,5,"pl-k"],[44,45,"pl-k"],[46,68,"pl-smi"],[69,72,"pl-en"]],[[0,3,"pl-s"]],[],[],[],[[0,2,"pl-s"],[5,7,"pl-s"],[11,12,"pl-s"],[12,18,"pl-c1"],[18,19,"pl-s"]],[],[[0,22,"pl-mh"],[4,22,"pl-en"]],[],[[0,3,"pl-s"],[3,13,"pl-en"]],[[0,8,"pl-k"],[33,42,"pl-v"]],[[2,5,"pl-k"],[7,12,"pl-k"],[7,12,"pl-k"],[20,22,"pl-k"],[23,42,"pl-en"],[49,56,"pl-c"],[49,51,"pl-c"]],[[4,9,"pl-k"],[4,9,"pl-k"],[18,19,"pl-k"],[20,37,"pl-en"],[38,44,"pl-smi"],[46,49,"pl-en"],[50,53,"pl-k"],[57,67,"pl-c"],[57,59,"pl-c"]],[[4,6,"pl-k"],[8,15,"pl-smi"],[16,24,"pl-en"],[25,35,"pl-smi"],[40,43,"pl-k"]],[],[],[[0,3,"pl-s"]],[],[[0,2,"pl-s"],[5,7,"pl-s"],[11,12,"pl-s"],[12,46,"pl-c1"],[46,47,"pl-s"]],[],[[0,20,"pl-mh"],[4,20,"pl-en"]],[],[[0,1,"pl-s"],[1,23,"pl-c1"],[23,24,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,13,"pl-c1"],[13,14,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,23,"pl-c1"],[23,24,"pl-s"]],[],[],[],[[0,2,"pl-s"],[5,7,"pl-s"],[15,16,"pl-s"],[16,33,"pl-c1"],[33,34,"pl-s"]],[],[[0,44,"pl-mh"],[4,44,"pl-en"]],[],[[0,1,"pl-ml"],[2,3,"pl-ml"],[18,19,"pl-ml"],[36,37,"pl-ml"]],[[0,1,"pl-ml"],[4,5,"pl-ml"],[8,9,"pl-ml"],[12,13,"pl-ml"]],[[0,1,"pl-ml"],[5,6,"pl-ml"],[21,22,"pl-ml"],[40,41,"pl-ml"]],[[0,1,"pl-ml"],[5,6,"pl-ml"],[35,36,"pl-ml"],[55,56,"pl-ml"]],[[0,1,"pl-ml"],[5,6,"pl-ml"],[14,15,"pl-ml"],[36,37,"pl-ml"]],[],[],[],[[0,2,"pl-s"],[5,7,"pl-s"]],[],[[0,34,"pl-mh"],[4,34,"pl-en"]],[],[[0,3,"pl-s"],[3,13,"pl-en"]],[[0,15,"pl-c"],[0,2,"pl-c"]],[[0,29,"pl-en"],[30,35,"pl-smi"],[36,46,"pl-smi"],[48,59,"pl-smi"]],[[0,16,"pl-c"],[0,2,"pl-c"]],[[0,29,"pl-en"],[30,35,"pl-smi"],[36,46,"pl-smi"],[48,59,"pl-smi"]],[[0,3,"pl-s"]],[],[[0,2,"pl-s"],[5,7,"pl-s"],[11,12,"pl-s"],[12,26,"pl-c1"],[26,27,"pl-s"]],[],[[0,36,"pl-mh"],[4,36,"pl-en"]],[],[[0,3,"pl-s"],[3,13,"pl-en"]],[[0,5,"pl-k"],[0,5,"pl-k"],[18,19,"pl-k"],[20,27,"pl-smi"],[29,36,"pl-smi"],[37,39,"pl-k"],[40,49,"pl-smi"],[50,51,"pl-c1"],[54,61,"pl-smi"]],[[0,3,"pl-s"]],[],[],[],[[0,2,"pl-s"],[5,7,"pl-s"]],[],[[0,18,"pl-mh"],[4,18,"pl-en"]],[],[[12,13,"pl-s"],[13,29,"pl-c1"],[29,30,"pl-s"],[38,39,"pl-s"],[39,60,"pl-c1"],[60,61,"pl-s"]],[],[[0,17,"pl-mh"],[4,17,"pl-en"]],[],[[0,1,"pl-s"],[1,24,"pl-c1"],[24,25,"pl-s"],[28,29,"pl-s"],[29,37,"pl-c1"],[37,38,"pl-s"],[48,49,"pl-s"],[49,72,"pl-c1"],[72,73,"pl-s"],[74,75,"pl-s"],[75,104,"pl-c1"],[104,105,"pl-s"]],[],[[0,16,"pl-mh"],[4,16,"pl-en"]],[],[],[],[[0,3,"pl-ms"]],[],[[0,13,"pl-mh"],[3,13,"pl-en"]],[],[[0,216,"pl-ent"],[0,2,"pl-ent"],[7,8,"pl-s"],[8,48,"pl-c1"],[48,49,"pl-s"],[50,51,"pl-s"],[51,87,"pl-c1"],[87,88,"pl-s"],[89,90,"pl-s"],[90,123,"pl-c1"],[123,124,"pl-s"],[125,126,"pl-s"],[126,158,"pl-c1"],[158,159,"pl-s"],[160,161,"pl-s"],[161,191,"pl-c1"],[191,192,"pl-s"],[193,194,"pl-s"],[194,215,"pl-c1"],[215,216,"pl-s"]],[[0,0,"pl-ent"]],[[0,28,"pl-mh"],[4,28,"pl-en"]],[],[[0,1,"pl-s"],[1,42,"pl-c1"],[42,43,"pl-s"]],[],[[0,29,"pl-mh"],[4,29,"pl-en"]],[],[[0,3,"pl-s"],[3,13,"pl-en"]],[[0,7,"pl-c"],[0,2,"pl-c"]],[[0,6,"pl-smi"],[7,11,"pl-en"],[12,37,"pl-s"],[12,13,"pl-pds"],[36,37,"pl-pds"],[39,42,"pl-k"]],[[0,6,"pl-smi"],[7,11,"pl-en"],[12,40,"pl-s"],[12,13,"pl-pds"],[39,40,"pl-pds"],[42,45,"pl-k"]],[[0,3,"pl-s"]],[],[[0,36,"pl-mh"],[4,36,"pl-en"],[8,9,"pl-s"],[9,23,"pl-c1"],[23,24,"pl-s"]],[],[[0,3,"pl-s"],[3,13,"pl-en"]],[[0,6,"pl-k"],[7,12,"pl-k"],[13,21,"pl-k"],[37,39,"pl-v"],[39,40,"pl-k"],[41,47,"pl-c1"],[48,49,"pl-k"],[50,57,"pl-en"],[58,65,"pl-c1"]],[[2,7,"pl-k"],[2,7,"pl-k"],[13,14,"pl-k"],[15,20,"pl-k"],[21,32,"pl-en"],[37,47,"pl-c"],[37,39,"pl-c"]],[[2,8,"pl-k"],[9,13,"pl-smi"],[14,21,"pl-smi"],[22,26,"pl-c1"],[27,30,"pl-k"],[33,37,"pl-smi"],[39,45,"pl-smi"],[46,49,"pl-k"],[50,54,"pl-c1"]],[],[[0,3,"pl-s"]],[],[[2,3,"pl-s"],[3,19,"pl-c1"],[19,20,"pl-s"]],[],[[0,2,"pl-s"],[5,7,"pl-s"]],[],[[0,25,"pl-mh"],[4,25,"pl-en"]],[],[],[],[[0,2,"pl-s"],[5,7,"pl-s"]],[],[[0,24,"pl-mh"],[4,24,"pl-en"]],[],[[0,3,"pl-s"],[3,13,"pl-en"]],[[0,6,"pl-k"],[7,11,"pl-k"],[12,20,"pl-en"],[21,22,"pl-k"]],[[8,9,"pl-k"],[10,17,"pl-c1"],[20,32,"pl-c"],[20,22,"pl-c"]],[[2,8,"pl-c"],[2,4,"pl-c"]],[],[[0,3,"pl-s"]],[],[[0,2,"pl-s"],[5,7,"pl-s"]],[],[[0,3,"pl-s"],[3,13,"pl-en"]],[[0,6,"pl-k"],[7,11,"pl-k"],[12,22,"pl-en"],[23,24,"pl-k"]],[[15,16,"pl-k"],[17,24,"pl-c1"]],[[21,22,"pl-k"],[23,30,"pl-c1"]],[[18,19,"pl-k"],[20,27,"pl-c1"]],[],[[0,3,"pl-s"]],[],[[0,18,"pl-mh"],[4,18,"pl-en"]],[],[[0,1,"pl-s"],[1,15,"pl-c1"],[15,16,"pl-s"],[31,32,"pl-s"],[32,49,"pl-c1"],[49,50,"pl-s"]],[],[[0,2,"pl-s"],[5,7,"pl-s"]],[],[[0,16,"pl-mh"],[4,16,"pl-en"]],[],[],[],[[0,2,"pl-s"],[5,7,"pl-s"]],[],[[0,25,"pl-mh"],[4,25,"pl-en"]],[],[[0,3,"pl-s"],[3,13,"pl-en"]],[[0,2,"pl-k"],[4,20,"pl-en"],[21,31,"pl-smi"],[37,50,"pl-c"],[37,39,"pl-c"]],[[2,5,"pl-k"]],[],[[0,2,"pl-k"],[4,10,"pl-smi"],[11,16,"pl-smi"],[17,20,"pl-k"],[21,30,"pl-s"],[21,22,"pl-pds"],[29,30,"pl-pds"],[31,33,"pl-k"],[34,37,"pl-k"],[42,56,"pl-c"],[42,44,"pl-c"]],[[2,5,"pl-k"]],[],[[0,3,"pl-s"]],[],[],[],[[0,2,"pl-s"],[5,7,"pl-s"]],[],[[0,18,"pl-mh"],[4,18,"pl-en"]],[],[[0,1,"pl-s"],[1,15,"pl-c1"],[15,16,"pl-s"],[23,24,"pl-s"],[24,34,"pl-c1"],[34,35,"pl-s"],[39,40,"pl-s"],[40,56,"pl-c1"],[56,57,"pl-s"]],[],[[0,2,"pl-s"],[5,7,"pl-s"]],[],[[0,17,"pl-mh"],[4,17,"pl-en"]],[],[[9,10,"pl-s"],[10,27,"pl-c1"],[27,28,"pl-s"],[34,35,"pl-s"],[35,48,"pl-c1"],[48,49,"pl-s"]],[],[[0,3,"pl-ms"]],[],[[0,16,"pl-mh"],[3,16,"pl-en"]],[],[[0,198,"pl-ent"],[0,2,"pl-ent"],[7,8,"pl-s"],[8,29,"pl-c1"],[29,30,"pl-s"],[31,32,"pl-s"],[32,74,"pl-c1"],[74,75,"pl-s"],[76,77,"pl-s"],[77,117,"pl-c1"],[117,118,"pl-s"],[119,120,"pl-s"],[120,161,"pl-c1"],[161,162,"pl-s"],[163,164,"pl-s"],[164,197,"pl-c1"],[197,198,"pl-s"]],[[0,0,"pl-ent"]],[[0,44,"pl-mh"],[4,44,"pl-en"],[8,9,"pl-s"],[9,28,"pl-c1"],[28,29,"pl-s"]],[],[[0,3,"pl-s"],[3,5,"pl-en"]],[[0,4,"pl-k"],[5,38,"pl-en"],[6,7,"pl-v"],[9,19,"pl-v"],[21,38,"pl-en"]],[[6,8,"pl-smi"],[9,13,"pl-c1"]],[[4,7,"pl-k"],[8,10,"pl-smi"],[12,16,"pl-smi"],[17,19,"pl-k"],[20,25,"pl-k"],[28,37,"pl-smi"]],[[12,18,"pl-c1"],[19,52,"pl-s"],[19,20,"pl-pds"],[49,51,"pl-c1"],[51,52,"pl-pds"],[63,66,"pl-smi"]],[],[[6,8,"pl-smi"],[9,15,"pl-c1"]],[],[[0,3,"pl-s"]],[],[[10,11,"pl-s"],[11,31,"pl-c1"],[31,32,"pl-s"],[37,38,"pl-s"],[38,46,"pl-c1"],[46,47,"pl-s"]],[],[[0,41,"pl-mh"],[4,41,"pl-en"],[8,9,"pl-s"],[9,19,"pl-c1"],[19,20,"pl-s"]],[],[[0,3,"pl-s"],[3,5,"pl-en"]],[[0,2,"pl-k"],[3,7,"pl-k"],[12,15,"pl-k"]],[[4,14,"pl-c1"],[15,21,"pl-s"],[15,16,"pl-pds"],[20,21,"pl-pds"],[23,27,"pl-s"],[23,24,"pl-pds"],[26,27,"pl-pds"],[33,40,"pl-c1"],[41,54,"pl-s"],[41,42,"pl-pds"],[47,49,"pl-c1"],[53,54,"pl-pds"],[62,65,"pl-c1"]],[[7,15,"pl-smi"]],[[0,6,"pl-c1"],[9,18,"pl-smi"],[24,34,"pl-smi"],[37,44,"pl-c"],[37,39,"pl-c"]],[[5,15,"pl-c1"],[19,25,"pl-c1"],[49,53,"pl-c1"],[57,64,"pl-c"],[57,59,"pl-c"]],[[0,3,"pl-s"]],[],[],[],[[0,27,"pl-mh"],[4,27,"pl-en"]],[],[[0,3,"pl-s"],[3,5,"pl-en"]],[[0,12,"pl-smi"],[13,15,"pl-k"],[16,17,"pl-c1"]],[[0,3,"pl-k"]],[[8,12,"pl-c1"]],[],[[4,15,"pl-c"],[4,6,"pl-c"]],[],[[0,3,"pl-s"]],[],[[0,1,"pl-s"],[1,11,"pl-c1"],[11,12,"pl-s"]],[],[[0,2,"pl-s"],[5,7,"pl-s"]],[],[[0,33,"pl-mh"],[4,33,"pl-en"]],[],[[0,1,"pl-ml"],[6,7,"pl-ml"],[11,12,"pl-ml"],[18,19,"pl-ml"]],[[0,1,"pl-ml"],[9,10,"pl-ml"],[16,17,"pl-ml"],[27,28,"pl-ml"]],[[0,1,"pl-ml"],[17,18,"pl-ml"],[19,20,"pl-s"],[20,36,"pl-c1"],[36,37,"pl-s"],[42,43,"pl-ml"],[57,58,"pl-ml"]],[[0,1,"pl-ml"],[10,11,"pl-ml"],[12,13,"pl-s"],[13,28,"pl-c1"],[28,29,"pl-s"],[32,33,"pl-s"],[33,50,"pl-c1"],[50,51,"pl-s"],[54,55,"pl-s"],[55,71,"pl-c1"],[71,72,"pl-s"],[73,74,"pl-ml"],[86,87,"pl-ml"]],[],[],[],[[0,2,"pl-s"],[5,7,"pl-s"]],[],[[0,32,"pl-mh"],[4,32,"pl-en"]],[],[],[],[[0,2,"pl-s"],[5,7,"pl-s"],[23,24,"pl-s"],[24,45,"pl-c1"],[45,46,"pl-s"]],[],[[0,31,"pl-mh"],[4,31,"pl-en"]],[],[[0,3,"pl-s"],[3,3,"pl-c1"]],[[0,38,"pl-c1"]],[[0,35,"pl-c1"]],[[0,27,"pl-c1"]],[[0,38,"pl-c1"]],[[0,0,"pl-c1"],[0,3,"pl-s"]],[],[[0,2,"pl-s"],[5,7,"pl-s"]],[],[[0,31,"pl-mh"],[4,31,"pl-en"]],[],[],[],[[0,2,"pl-s"],[5,7,"pl-s"]],[],[[0,37,"pl-mh"],[4,37,"pl-en"],[8,9,"pl-s"],[9,19,"pl-c1"],[19,20,"pl-s"]],[],[[18,19,"pl-s"],[19,30,"pl-c1"],[30,31,"pl-s"],[37,38,"pl-s"],[38,44,"pl-c1"],[44,45,"pl-s"],[60,61,"pl-s"],[61,75,"pl-c1"],[75,76,"pl-s"],[85,86,"pl-s"],[86,89,"pl-c1"],[89,90,"pl-s"]],[],[[0,2,"pl-s"],[5,7,"pl-s"],[10,11,"pl-s"],[11,29,"pl-c1"],[29,30,"pl-s"]],[],[[0,24,"pl-mh"],[4,24,"pl-en"]],[],[[0,3,"pl-s"],[3,13,"pl-en"]],[[0,2,"pl-k"],[4,34,"pl-sr"],[4,5,"pl-pds"],[15,16,"pl-k"],[20,22,"pl-cce"],[33,34,"pl-pds"],[35,39,"pl-c1"],[40,44,"pl-smi"],[47,57,"pl-smi"],[58,59,"pl-k"],[60,66,"pl-s"],[60,61,"pl-pds"],[65,66,"pl-pds"]],[[0,3,"pl-s"]],[],[[0,1,"pl-s"],[1,24,"pl-c1"],[24,25,"pl-s"]],[],[[0,33,"pl-mh"],[4,33,"pl-en"]],[],[[9,10,"pl-s"],[10,29,"pl-c1"],[29,30,"pl-s"]],[],[[0,2,"pl-s"],[5,7,"pl-s"]],[],[[0,39,"pl-mh"],[4,39,"pl-en"],[9,10,"pl-s"],[10,26,"pl-c1"],[26,27,"pl-s"]],[],[[0,3,"pl-s"],[3,5,"pl-en"]],[[2,9,"pl-smi"],[10,17,"pl-smi"],[18,22,"pl-c1"],[26,39,"pl-c"],[26,28,"pl-c"]],[[0,3,"pl-s"]],[],[],[],[[0,2,"pl-s"],[5,7,"pl-s"]],[],[[0,22,"pl-mh"],[4,22,"pl-en"]],[],[[0,1,"pl-s"],[1,13,"pl-c1"],[13,14,"pl-s"],[19,20,"pl-s"],[20,33,"pl-c1"],[33,34,"pl-s"]],[],[[0,3,"pl-ms"]],[],[[0,10,"pl-mh"],[3,10,"pl-en"]],[],[[0,190,"pl-ent"],[0,2,"pl-ent"],[7,8,"pl-s"],[8,44,"pl-c1"],[44,45,"pl-s"],[46,47,"pl-s"],[47,86,"pl-c1"],[86,87,"pl-s"],[88,89,"pl-s"],[89,145,"pl-c1"],[145,146,"pl-s"],[147,148,"pl-s"],[148,189,"pl-c1"],[189,190,"pl-s"]],[[0,0,"pl-ent"]],[[0,29,"pl-mh"],[4,29,"pl-en"]],[],[[0,3,"pl-s"],[3,6,"pl-en"]],[[0,7,"pl-k"],[8,11,"pl-c1"],[12,116,"pl-s"],[12,13,"pl-pds"],[115,116,"pl-pds"]],[[0,3,"pl-s"]],[],[],[],[[0,2,"pl-s"],[5,7,"pl-s"],[20,21,"pl-s"],[21,31,"pl-c1"],[31,32,"pl-s"],[35,36,"pl-s"],[36,41,"pl-c1"],[41,42,"pl-s"]],[],[[0,37,"pl-mh"],[4,37,"pl-en"]],[],[[0,1,"pl-s"],[19,20,"pl-s"],[20,21,"pl-s"],[21,99,"pl-corl"],[99,100,"pl-s"],[107,108,"pl-s"],[108,110,"pl-c1"],[110,111,"pl-s"],[115,116,"pl-s"],[116,120,"pl-c1"],[120,121,"pl-s"],[122,123,"pl-s"],[123,127,"pl-c1"],[127,128,"pl-s"],[129,130,"pl-s"],[130,134,"pl-c1"],[134,135,"pl-s"]],[],[[0,2,"pl-s"],[5,7,"pl-s"],[8,9,"pl-s"],[9,11,"pl-c1"],[11,12,"pl-s"],[15,16,"pl-s"],[16,19,"pl-c1"],[19,20,"pl-s"]],[],[[0,24,"pl-mh"],[4,24,"pl-en"]],[],[[0,1,"pl-s"],[1,12,"pl-c1"],[12,13,"pl-s"],[18,19,"pl-s"],[19,38,"pl-c1"],[38,39,"pl-s"],[47,48,"pl-s"],[48,70,"pl-c1"],[70,71,"pl-s"]],[],[[0,2,"pl-s"],[5,7,"pl-s"],[11,12,"pl-s"],[12,26,"pl-c1"],[26,27,"pl-s"],[35,36,"pl-s"],[36,51,"pl-c1"],[51,52,"pl-s"],[55,56,"pl-s"],[56,72,"pl-c1"],[72,73,"pl-s"]],[],[[0,26,"pl-mh"],[4,26,"pl-en"]],[],[[0,1,"pl-s"],[10,11,"pl-s"],[11,12,"pl-s"],[12,80,"pl-corl"],[80,81,"pl-s"],[90,91,"pl-s"],[91,130,"pl-c1"],[130,131,"pl-s"]],[],[[0,2,"pl-s"],[5,7,"pl-s"],[46,47,"pl-s"],[47,58,"pl-c1"],[58,59,"pl-s"]],[],[[0,34,"pl-mh"],[4,34,"pl-en"]],[],[[0,3,"pl-s"],[3,13,"pl-en"]],[[0,5,"pl-en"],[7,16,"pl-s"],[7,8,"pl-pds"],[15,16,"pl-pds"],[18,30,"pl-c"],[18,20,"pl-c"]],[[0,5,"pl-en"],[7,16,"pl-s"],[7,8,"pl-pds"],[15,16,"pl-pds"]],[[0,5,"pl-en"],[7,16,"pl-s"],[7,8,"pl-pds"],[15,16,"pl-pds"],[18,28,"pl-c"],[18,20,"pl-c"]],[[0,3,"pl-s"]],[],[[0,2,"pl-s"],[5,7,"pl-s"]],[],[[0,28,"pl-mh"],[4,28,"pl-en"]],[],[[0,1,"pl-s"],[19,20,"pl-s"],[20,21,"pl-s"],[21,84,"pl-corl"],[84,85,"pl-s"],[99,100,"pl-s"],[100,107,"pl-c1"],[107,108,"pl-s"],[109,110,"pl-s"],[110,122,"pl-c1"],[122,123,"pl-s"]],[],[[0,18,"pl-mh"],[4,18,"pl-en"]],[],[[10,11,"pl-s"],[11,26,"pl-c1"],[26,27,"pl-s"]],[],[[0,2,"pl-s"],[5,7,"pl-s"],[12,13,"pl-s"],[13,28,"pl-c1"],[28,29,"pl-s"]],[],[[0,18,"pl-mh"],[4,18,"pl-en"]],[],[],[],[[0,22,"pl-mh"],[4,22,"pl-en"]],[],[[6,7,"pl-s"],[7,31,"pl-c1"],[31,32,"pl-s"],[38,39,"pl-s"],[39,87,"pl-c1"],[87,88,"pl-s"]],[],[[0,23,"pl-mh"],[4,23,"pl-en"]],[],[[4,5,"pl-s"],[5,30,"pl-c1"],[30,31,"pl-s"]],[],[[0,23,"pl-mh"],[4,23,"pl-en"]],[],[[0,3,"pl-s"],[3,6,"pl-en"]],[[0,5,"pl-e"],[8,13,"pl-c1"],[8,13,"pl-c1"],[15,22,"pl-c1"],[27,45,"pl-c"],[27,29,"pl-c"],[43,45,"pl-c"]],[[0,3,"pl-s"]],[],[],[],[[0,42,"pl-mh"],[4,42,"pl-en"],[9,10,"pl-s"],[10,14,"pl-c1"],[14,15,"pl-s"],[19,20,"pl-s"],[20,24,"pl-c1"],[24,25,"pl-s"],[30,31,"pl-s"],[31,37,"pl-c1"],[37,38,"pl-s"]],[],[[0,1,"pl-s"],[1,16,"pl-c1"],[16,17,"pl-s"],[32,33,"pl-s"],[33,51,"pl-c1"],[51,52,"pl-s"]],[],[[0,3,"pl-ms"]],[],[[0,10,"pl-mh"],[3,10,"pl-en"]],[],[[0,1,"pl-ml"],[6,7,"pl-ml"],[12,13,"pl-ml"],[19,20,"pl-ml"]],[[0,1,"pl-ml"],[9,10,"pl-ml"],[18,19,"pl-ml"],[29,30,"pl-ml"]],[[0,1,"pl-ml"],[2,4,"pl-s"],[6,8,"pl-s"],[9,10,"pl-ml"],[13,14,"pl-ml"],[41,42,"pl-ml"]],[[0,1,"pl-ml"],[2,4,"pl-s"],[6,8,"pl-s"],[9,10,"pl-ml"],[14,15,"pl-ml"],[35,36,"pl-ml"]],[[0,1,"pl-ml"],[2,4,"pl-s"],[6,8,"pl-s"],[9,10,"pl-ml"],[15,16,"pl-ml"],[21,22,"pl-ml"]]],"colorizedLines":null}},"title":"nova-studio/BUG_ANALYSIS.md at main · fuxingliang/nova-studio","appPayload":{},"meta":{"title":"nova-studio/BUG_ANALYSIS.md at main · fuxingliang/nova-studio"}}</script>
  <div data-target="react-app.reactRoot"><meta name="github-code-view-meta-stats" id="github-code-view-meta-stats" data-hydrostats="publish"/> <!-- --> <a hidden="" id="code-view-repo-link" href="/fuxingliang/nova-studio" data-discover="true"></a> <div class="d-none"></div><div><div style="--spacing:var(--spacing-none)" class="prc-PageLayout-PageLayoutRoot--KH-d" data-component="SplitPageLayout" data-has-sidebar="true"><div class="prc-PageLayout-SidebarWrapper-kLG4B CopilotSidePanelSidebar-module__SidePanel__L3O0C CopilotSidePanelSidebar-module__HiddenSidePanel__TBRGn" style="--spacing-column:var(--spacing-none)" data-is-hidden="false" data-position="end" data-sticky="true" data-responsive-variant="fullscreen"><div class="prc-PageLayout-VerticalDivider-9QRmK prc-PageLayout-SidebarVerticalDivider-0Rl0V" data-component="PageLayout.VerticalDivider" data-variant="line" data-position="end" style="--spacing:var(--spacing-none)"><div class="prc-PageLayout-DraggableHandle-9s6B4" data-component="PageLayout.DragHandle" role="slider" aria-label="Draggable pane splitter" aria-valuemin="450" aria-valuemax="768" aria-valuenow="544" aria-valuetext="Pane width 544 pixels" tabindex="0"></div></div><div class="prc-PageLayout-Sidebar-iciWg" data-component="SplitPageLayout.Sidebar" data-resizable="true" style="--spacing:var(--spacing-normal);--pane-min-width:450px;--pane-max-width:768px;--pane-width-custom:544px;--pane-width-size:var(--pane-width-custom);--pane-width:544px"><div class="height-full" data-testid="copilot-code-view-side-panel"><div id="copilot-side-panel-content" class="height-full"></div></div></div></div><div class="prc-PageLayout-PageLayoutWrapper-2BhU2" data-width="full"><div class="prc-PageLayout-PageLayoutContent-BneH9"><div id="repos-file-tree-sidebar" class="CodeViewFileTreeLayout-module__sidebar__n_Aau" tabindex="0"><div class="prc-PageLayout-PaneWrapper-pHPop ReposFileTreePane-module__Pane__rBZpI ReposFileTreePane-module__HideTree__AYZnm ReposFileTreePane-module__HidePane__VHAVt" style="--offset-header:0px;--spacing-row:var(--spacing-none);--spacing-column:var(--spacing-none)" data-is-hidden="false" data-position="start" data-sticky="true"><div class="prc-PageLayout-HorizontalDivider-JLVqp prc-PageLayout-PaneHorizontalDivider-9tbnE" data-component="PageLayout.HorizontalDivider" data-variant-regular="none" data-variant-narrow="none" data-position="start" style="--spacing-divider:var(--spacing-none);--spacing:var(--spacing-none)"></div><div class="prc-PageLayout-Pane-AyzHK" data-component="SplitPageLayout.Pane" data-resizable="true" style="--spacing:var(--spacing-none);--pane-min-width:256px;--pane-max-width:calc(100vw - var(--pane-max-width-diff));--pane-width-size:var(--pane-width-large);--pane-width:320px"></div><div class="prc-PageLayout-VerticalDivider-9QRmK prc-PageLayout-PaneVerticalDivider-le57g" data-component="PageLayout.VerticalDivider" data-variant-narrow="none" data-variant-regular="line" data-variant-wide="line" data-position="start" style="--spacing:var(--spacing-none)"><div class="prc-PageLayout-DraggableHandle-9s6B4" data-component="PageLayout.DragHandle" role="slider" aria-label="Draggable pane splitter" aria-valuemin="256" aria-valuemax="600" aria-valuenow="320" aria-valuetext="Pane width 320 pixels" tabindex="0"></div></div></div></div><div data-component="SplitPageLayout.Content" class="prc-PageLayout-ContentWrapper-gR9eG"><div class="prc-PageLayout-Content-xWL-A" data-width="full" style="--spacing:var(--spacing-none)"><div class="SharedPageLayout-module__content__IwGAp" data-selector="repos-split-pane-content" id="repos-split-pane-content" tabindex="0"> <!-- --> <div class="container CodeViewHeader-module__Box__JkPOb"><div class="CodeViewHeader-module__StickyHeader__Qn7UN" id="StickyHeader"><div class="CodeViewHeader-module__Box_1__SbNDV"><div class="CodeViewHeader-module__Box_2__TB46f"><div class="react-code-view-header-wrap--narrow CodeViewHeader-module__Box_3__q1zUL"><div class="CodeViewHeader-module__treeToggleWrapper__RQ__9"><h2 class="use-tree-pane-module__Heading__s4QbZ prc-Heading-Heading-MtWFE" data-component="Heading"><button data-component="Button" type="button" aria-label="Expand file tree" data-testid="expand-file-tree-button-mobile" class="prc-Button-ButtonBase-9n-Xk ExpandFileTreeButton-module__Button_1__Svs95" data-loading="false" data-size="medium" data-variant="invisible"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-arrow-left" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.78 12.53a.75.75 0 0 1-1.06 0L2.47 8.28a.75.75 0 0 1 0-1.06l4.25-4.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L4.81 7h7.44a.75.75 0 0 1 0 1.5H4.81l2.97 2.97a.75.75 0 0 1 0 1.06Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3">Files</span></span></button><button data-component="IconButton" type="button" data-testid="expand-file-tree-button" aria-controls="repos-file-tree" class="prc-Button-ButtonBase-9n-Xk position-relative ExpandFileTreeButton-module__expandButton__hDOcv ExpandFileTreeButton-module__filesButtonBreakpoint__zEvz3 fgColor-muted prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="invisible" aria-labelledby="_R_4lla9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-sidebar-collapse" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.823 7.823a.25.25 0 0 1 0 .354l-2.396 2.396A.25.25 0 0 1 4 10.396V5.604a.25.25 0 0 1 .427-.177Z"></path><path d="M1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25V1.75C0 .784.784 0 1.75 0ZM1.5 1.75v12.5c0 .138.112.25.25.25H9.5v-13H1.75a.25.25 0 0 0-.25.25ZM11 14.5h3.25a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25H11Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="se" data-component="Tooltip" aria-hidden="true" id="_R_4lla9lik5_">Expand file tree</span><div class="d-none"></div></h2></div><div class="react-code-view-header-mb--narrow mr-2"><button data-component="Button" type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-label="main branch" data-testid="anchor-button" data-icv-name="Switch branches/tags" class="prc-Button-ButtonBase-9n-Xk ref-selector-class RefSelectorAnchoredOverlay-module__RefSelectorOverlayBtn__a3WK3" data-loading="false" data-size="medium" data-variant="default" id="ref-picker-repos-header-ref-selector-wide"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-git-branch" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3"><div class="RefSelectorAnchoredOverlay-module__RefSelectorOverlayContainer__yaf4p"><div style="max-width:125px" class="ref-selector-button-text-container RefSelectorAnchoredOverlay-module__RefSelectorBtnTextContainer__Di3rk"><span class="RefSelectorAnchoredOverlay-module__RefSelectorText__w_fmP">main</span></div></div></span><span data-component="trailingVisual" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></span></button><div class="d-none"></div></div><div class="react-code-view-header-mb--narrow CodeViewHeader-module__Box_5__MQ0hL"><div class="Breadcrumb-module__container__Vxvev Breadcrumb-module__lg__Rjz0A"><nav data-testid="breadcrumbs" aria-labelledby="repos-header-breadcrumb-heading" id="repos-header-breadcrumb" class="Breadcrumb-module__nav__rQFDj"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading" id="repos-header-breadcrumb-heading">Breadcrumbs</h2><ol class="Breadcrumb-module__list__ZH6zr"><li class="Breadcrumb-module__listItem__Ib0x_"><a class="Breadcrumb-module__repoLink__O2Nbs prc-Link-Link-9ZwDx" data-component="Link" data-testid="breadcrumbs-repo-link" href="/fuxingliang/nova-studio/tree/main" data-discover="true">nova-studio</a></li></ol></nav><div data-testid="breadcrumbs-filename" class="Breadcrumb-module__filename__equZR"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__lg__Rjz0A" aria-hidden="true">/</span><h1 class="Breadcrumb-module__filenameHeading__MNMtw Breadcrumb-module__lg__Rjz0A prc-Heading-Heading-MtWFE" data-component="Heading" tabindex="-1" id="file-name-id">BUG_ANALYSIS.md</h1></div><button data-component="IconButton" type="button" class="prc-Button-ButtonBase-9n-Xk ml-2 prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_7lla9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copy" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><span class="CopyToClipboardIconButton-module__tooltip__WyiwL prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-label="Copy path" aria-hidden="true" id="_R_7lla9lik5_">Copy path</span></div></div></div><div class="react-code-view-header-element--wide"><div class="CodeViewHeader-module__Box_7___0R6c"><div class="d-flex gap-2"><div><div class="CodeViewHeader-module__FileResultsList__JDzUy"><span class="d-flex FileResultsList-module__FilesSearchBox__ivVkc TextInput-wrapper prc-components-TextInputWrapper-Hpdqi prc-components-TextInputBaseWrapper-wY-n0" data-no-trailing-action="true" data-component="TextInput" data-leading-visual="true" data-trailing-visual="true" aria-busy="false"><span class="TextInput-icon" id="_R_1cpla9lik5_" aria-hidden="true" data-component="TextInput.LeadingVisual"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-search" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path></svg></span><input type="text" aria-label="Go to file" role="combobox" aria-controls="file-results-list" aria-expanded="false" aria-haspopup="dialog" autoCorrect="off" spellCheck="false" placeholder="Go to file" aria-describedby="_R_1cpla9lik5_ _R_1cpla9lik5H1_" data-component="input" class="prc-components-Input-IwWrt" value=""/><span class="TextInput-icon" id="_R_1cpla9lik5H1_" aria-hidden="true" data-component="TextInput.TrailingVisual"></span></span></div><div class="d-none"></div></div><button data-component="Button" type="button" style="display:none" class="prc-Button-ButtonBase-9n-Xk NavigationMenu-module__Button__LpKgm" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3">Blame</span></span></button><div class="d-none"></div><button data-component="IconButton" type="button" data-testid="more-file-actions-button-nav-menu-wide" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk js-blob-dropdown-click NavigationMenu-module__IconButton__HpX3G prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default" aria-labelledby="_R_7p9la9lik5_" id="_R_99la9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-hidden="true" id="_R_7p9la9lik5_">More file actions</span></div></div></div><div class="react-code-view-header-element--narrow"><div class="CodeViewHeader-module__Box_7___0R6c"><div class="d-flex gap-2"><button data-component="Button" type="button" style="display:none" class="prc-Button-ButtonBase-9n-Xk NavigationMenu-module__Button__LpKgm" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3">Blame</span></span></button><div class="d-none"></div><button data-component="IconButton" type="button" data-testid="more-file-actions-button-nav-menu-narrow" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk js-blob-dropdown-click NavigationMenu-module__IconButton__HpX3G prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default" aria-labelledby="_R_7pdla9lik5_" id="_R_9dla9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-hidden="true" id="_R_7pdla9lik5_">More file actions</span></div></div></div></div></div></div></div><div class="CodeView-module__contentWrapper__cG2JH"><div class="react-code-view-bottom-padding"><div class="BlobTopBanners-module__Box__v_nvx"></div></div> <div class="d-none"></div><div class="d-flex flex-column border rounded-2 tmp-mb-3 pl-1"><div class="LatestCommit-module__Box__B25ZT"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading">Latest commit</h2><div style="width:120px" class="Skeleton Skeleton--text" data-testid="loading"> </div><div class="d-flex flex-shrink-0 gap-2"><div data-testid="latest-commit-details" class="d-none d-sm-flex flex-items-center"></div><div class="d-flex gap-2"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading">History</h2><a data-component="LinkButton" href="/fuxingliang/nova-studio/commits/main/BUG_ANALYSIS.md" class="prc-Button-ButtonBase-9n-Xk d-none d-lg-flex LinkButton-module__linkButton__nFnov flex-items-center fgColor-default" data-loading="false" data-size="small" data-variant="invisible"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-history" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3"><span class="fgColor-default">History</span></span></span></a><div class="d-sm-none"></div><div class="d-flex d-lg-none"><a data-component="LinkButton" aria-label="View commit history for this file." href="/fuxingliang/nova-studio/commits/main/BUG_ANALYSIS.md" class="prc-Button-ButtonBase-9n-Xk LinkButton-module__linkButton__nFnov flex-items-center fgColor-default" data-loading="false" data-size="small" data-variant="invisible" aria-describedby="_R_4mlala9lik5_"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-history" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path></svg></span></span></a><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="s" data-component="Tooltip" role="tooltip" aria-hidden="true" id="_R_4mlala9lik5_">History</span></div></div></div></div></div><div class="d-flex flex-row"><div class="container BlobViewContent-module__blobContainer__DtH2d"><div class="react-code-size-details-banner BlobViewContent-module__codeSizeDetails__e5sUw"><div class="react-code-size-details-banner CodeSizeDetails-module__Box__VcD6l"><div class="text-mono CodeSizeDetails-module__Box_1__GVxQL"><div data-testid="blob-size" class="CodeSizeDetails-module__Truncate_1__lE93V prc-Truncate-Truncate-2G1eo" data-inline="true" title="17 KB" style="--truncate-max-width:100%"><span>494 lines (310 loc) · 17 KB</span></div></div></div></div><div class="react-blob-view-header-sticky BlobViewContent-module__stickyHeader__VwxB5" id="repos-sticky-header"><div class="BlobViewHeader-module__Box__yhm9u"><div class="react-blob-sticky-header"><div class="FileNameStickyHeader-module__outerWrapper__ZL4Xc FileNameStickyHeader-module__outerWrapperHidden__Zpynk"><div class="FileNameStickyHeader-module__Box_1__Hazu5"><div class="FileNameStickyHeader-module__Box_2__hoolP"><div class="FileNameStickyHeader-module__Box_3__MVKsk"><button data-component="Button" type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-label="main branch" data-testid="anchor-button" data-icv-name="Switch branches/tags" class="prc-Button-ButtonBase-9n-Xk ref-selector-class RefSelectorAnchoredOverlay-module__RefSelectorOverlayBtn__a3WK3" data-loading="false" data-size="medium" data-variant="default" id="ref-picker-repos-header-ref-selector"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-git-branch" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3"><div class="RefSelectorAnchoredOverlay-module__RefSelectorOverlayContainer__yaf4p"><div style="max-width:125px" class="ref-selector-button-text-container RefSelectorAnchoredOverlay-module__RefSelectorBtnTextContainer__Di3rk"><span class="RefSelectorAnchoredOverlay-module__RefSelectorText__w_fmP">main</span></div></div></span><span data-component="trailingVisual" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></span></button><div class="d-none"></div></div><div class="FileNameStickyHeader-module__Box_4__FLhtt"><div class="Breadcrumb-module__container__Vxvev Breadcrumb-module__md__Wb1Gs"><nav data-testid="breadcrumbs" aria-labelledby="sticky-breadcrumb-heading" id="sticky-breadcrumb" class="Breadcrumb-module__nav__rQFDj"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading" id="sticky-breadcrumb-heading">Breadcrumbs</h2><ol class="Breadcrumb-module__list__ZH6zr"><li class="Breadcrumb-module__listItem__Ib0x_"><a class="Breadcrumb-module__repoLink__O2Nbs prc-Link-Link-9ZwDx" data-component="Link" data-testid="breadcrumbs-repo-link" href="/fuxingliang/nova-studio/tree/main" data-discover="true">nova-studio</a></li></ol></nav><div data-testid="breadcrumbs-filename" class="Breadcrumb-module__filename__equZR"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__md__Wb1Gs" aria-hidden="true">/</span><h1 class="Breadcrumb-module__filenameHeading__MNMtw Breadcrumb-module__md__Wb1Gs prc-Heading-Heading-MtWFE" data-component="Heading" tabindex="-1" id="sticky-file-name-id">BUG_ANALYSIS.md</h1></div><button data-component="IconButton" type="button" class="prc-Button-ButtonBase-9n-Xk ml-2 prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_7lcpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copy" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><span class="CopyToClipboardIconButton-module__tooltip__WyiwL prc-TooltipV2-Tooltip-tLeuB" data-direction="s" data-component="Tooltip" aria-label="Copy path" aria-hidden="true" id="_R_7lcpala9lik5_">Copy path</span></div></div></div><button data-component="Button" type="button" class="prc-Button-ButtonBase-9n-Xk FileNameStickyHeader-module__Button__LSEU_ FileNameStickyHeader-module__GoToTopButton__nxAFn" data-loading="false" data-size="small" data-variant="invisible"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-arrow-up" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.47 7.78a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0l4.25 4.25a.751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018L9 4.81v7.44a.75.75 0 0 1-1.5 0V4.81L4.53 7.78a.75.75 0 0 1-1.06 0Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3">Top</span></span></button></div></div></div><div class="BlobViewHeader-module__Box_1__VEmuQ"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading">File metadata and controls</h2><div class="BlobViewHeader-module__Box_2__icUs2"><ul aria-label="File view" class="prc-SegmentedControl-SegmentedControl-lqIXp BlobTabButtons-module__SegmentedControl__jen2u" data-variant="default" data-size="small" data-component="SegmentedControl"><li class="prc-SegmentedControl-Item-tSCQh" data-selected="" data-component="SegmentedControl.Button"><button aria-pressed="true" class="prc-SegmentedControl-Button-E48xz" type="button" style="--separator-color:transparent"><span class="prc-SegmentedControl-Content-1COlk segmentedControl-content"><div class="prc-SegmentedControl-Text-7S2y2 segmentedControl-text" data-text="Preview">Preview</div></span></button></li><li class="prc-SegmentedControl-Item-tSCQh" data-component="SegmentedControl.Button"><button aria-pressed="false" class="prc-SegmentedControl-Button-E48xz" type="button" style="--separator-color:var(--borderColor-default)"><span class="prc-SegmentedControl-Content-1COlk segmentedControl-content"><div class="prc-SegmentedControl-Text-7S2y2 segmentedControl-text" data-text="Code">Code</div></span></button></li><li class="prc-SegmentedControl-Item-tSCQh" data-component="SegmentedControl.Button"><button aria-pressed="false" class="prc-SegmentedControl-Button-E48xz" type="button" style="--separator-color:var(--borderColor-default)"><span class="prc-SegmentedControl-Content-1COlk segmentedControl-content"><div class="prc-SegmentedControl-Text-7S2y2 segmentedControl-text" data-text="Blame">Blame</div></span></button></li></ul><div class="d-none"></div><div class="react-code-size-details-in-header CodeSizeDetails-module__Box__VcD6l"><div class="text-mono CodeSizeDetails-module__Box_1__GVxQL"><div data-testid="blob-size" class="CodeSizeDetails-module__Truncate_1__lE93V prc-Truncate-Truncate-2G1eo" data-inline="true" title="17 KB" style="--truncate-max-width:100%"><span>494 lines (310 loc) · 17 KB</span></div></div></div></div><div class="BlobViewHeader-module__Box_3__ng6v2"><div class="d-none"></div><div class="react-blob-header-edit-and-raw-actions BlobViewHeader-module__Box_4__J4Y4W"><div class="d-none"></div><div class="prc-ButtonGroup-ButtonGroup-vFUrY" data-component="ButtonGroup"><div class="prc-ButtonGroup-Item-PqvDl"><a data-component="LinkButton" href="https://github.com/fuxingliang/nova-studio/raw/refs/heads/main/BUG_ANALYSIS.md" data-testid="raw-button" class="prc-Button-ButtonBase-9n-Xk LinkButton-module__linkButton__nFnov BlobViewHeader-module__LinkButton__X9kx2" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3">Raw</span></span></a></div><div class="prc-ButtonGroup-Item-PqvDl"><button data-component="IconButton" type="button" data-testid="copy-raw-button" class="prc-Button-ButtonBase-9n-Xk prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default" aria-labelledby="_R_qaucpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copy" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="n" data-component="Tooltip" aria-hidden="true" id="_R_qaucpala9lik5_">Copy raw file</span></div><div class="prc-ButtonGroup-Item-PqvDl"><button data-component="IconButton" type="button" data-testid="download-raw-button" class="prc-Button-ButtonBase-9n-Xk BlobViewHeader-module__downloadButton__ef459 prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default" aria-labelledby="_R_eaucpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-download" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2.75 14A1.75 1.75 0 0 1 1 12.25v-2.5a.75.75 0 0 1 1.5 0v2.5c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25v-2.5a.75.75 0 0 1 1.5 0v2.5A1.75 1.75 0 0 1 13.25 14Z"></path><path d="M7.25 7.689V2a.75.75 0 0 1 1.5 0v5.689l1.97-1.969a.749.749 0 1 1 1.06 1.06l-3.25 3.25a.749.749 0 0 1-1.06 0L4.22 6.78a.749.749 0 1 1 1.06-1.06l1.97 1.969Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="n" data-component="Tooltip" aria-hidden="true" id="_R_eaucpala9lik5_">Download raw file</span></div></div></div><button data-component="IconButton" type="button" aria-pressed="false" class="prc-Button-ButtonBase-9n-Xk tmp-mr-2 TableOfContents-module__IconButton__jrlNM prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_3ucpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-list-unordered" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M5.75 2.5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5Zm0 5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5Zm0 5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5ZM2 14a1 1 0 1 1 0-2 1 1 0 0 1 0 2Zm1-6a1 1 0 1 1-2 0 1 1 0 0 1 2 0ZM2 4a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="n" data-component="Tooltip" aria-hidden="true" id="_R_3ucpala9lik5_">Outline</span><div class="react-blob-header-edit-and-raw-actions-combined"><button data-component="IconButton" type="button" title="More file actions" data-testid="more-file-actions-button" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk js-blob-dropdown-click BlobViewHeader-module__IconButton__XrMQY prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_fkecpala9lik5_" id="_R_kecpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-hidden="true" id="_R_fkecpala9lik5_">Edit and raw actions</span></div></div></div></div><div></div></div><div class="BlobViewContent-module__blobContentWrapper__JS0W6"><section aria-labelledby="file-name-id-wide file-name-id-mobile" class="BlobContent-module__blobContentSection__VOgZq BlobContent-module__blobContentSectionMarkdown__mPLOK" style="margin-top:46px"><div class="js-snippet-clipboard-copy-unpositioned BlobContent-module__markdownBlob__T8jpG" data-hpc="true" containertiming="hpc"><article class="markdown-body entry-content container-lg" itemprop="text"><div class="markdown-heading" dir="auto"><h1 tabindex="-1" class="heading-element" dir="auto">vLLM Launcher 问题分析报告</h1><a id="user-content-vllm-launcher-问题分析报告" class="anchor" aria-label="Permalink: vLLM Launcher 问题分析报告" href="#vllm-launcher-问题分析报告"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<blockquote>
<p dir="auto">生成日期：2026-08-08
状态：待修复</p>
</blockquote>
<hr>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">目录</h2><a id="user-content-目录" class="anchor" aria-label="Permalink: 目录" href="#目录"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<ul dir="auto">
<li><a href="#%E4%B8%80%E6%82%AC%E6%B5%AE%E7%AA%97%E9%9D%A2%E6%9D%BFfloatingbar">一、悬浮窗面板（FloatingBar）</a></li>
<li><a href="#%E4%BA%8C%E4%B8%BB%E9%A2%98%E6%A0%B7%E5%BC%8F">二、主题样式</a></li>
<li><a href="#%E4%B8%89gateway-%E7%BD%91%E5%85%B3%E5%A4%84%E7%90%86">三、Gateway 网关处理</a></li>
<li><a href="#%E5%9B%9B%E6%A8%A1%E5%9E%8B%E5%AE%9E%E4%BE%8B%E5%8A%A0%E9%94%81%E6%8A%80%E6%9C%AF">四、模型实例加锁技术</a></li>
<li><a href="#%E4%BA%94%E8%BF%9B%E7%A8%8B%E5%A4%84%E7%90%86go-%E5%85%A5%E5%8F%A3">五、进程处理（Go 入口）</a></li>
<li><a href="#%E5%85%AD%E5%AD%97%E4%BD%93%E5%92%8C%E9%A2%9C%E8%89%B2">六、字体和颜色</a></li>
</ul>
<hr>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">一、悬浮窗面板（FloatingBar）</h2><a id="user-content-一悬浮窗面板floatingbar" class="anchor" aria-label="Permalink: 一、悬浮窗面板（FloatingBar）" href="#一悬浮窗面板floatingbar"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<blockquote>
<p dir="auto">相关文件：<code>vllm-launcher/frontend/src/components/FloatingBar.tsx</code></p>
</blockquote>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">1.1 右侧 2×2 控制按钮区过于臃肿</h3><a id="user-content-11-右侧-22-控制按钮区过于臃肿" class="anchor" aria-label="Permalink: 1.1 右侧 2×2 控制按钮区过于臃肿" href="#11-右侧-22-控制按钮区过于臃肿"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">右侧占据 <code>grid-cols-2 gap-1</code> 的 2×2 网格（折叠/自动隐藏/收起/恢复），约 56px 宽度，4 个 12-14px 小图标辨识度差，"折叠"和"收起"语义易混淆。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">1.2 信息密度过高，视觉层级混乱</h3><a id="user-content-12-信息密度过高视觉层级混乱" class="anchor" aria-label="Permalink: 1.2 信息密度过高，视觉层级混乱" href="#12-信息密度过高视觉层级混乱"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">第一行从左到右塞了 10+ 个元素（Logo → 停止 → 思考下拉框 → 阶段指示器 → TPS → Token → 预填充 → 进度条 → 耗时 → 实例切换器 → 运行计数 → 启动计数），无主次分组。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">1.3 第二行条件性出现导致布局跳动</h3><a id="user-content-13-第二行条件性出现导致布局跳动" class="anchor" aria-label="Permalink: 1.3 第二行条件性出现导致布局跳动" href="#13-第二行条件性出现导致布局跳动"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">第二行（模型信息卡 + 压缩下拉框）在 <code>infoCollapsed</code> 或 <code>showStartup</code> 时整行消失，横栏内容上下跳动。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">1.4 模型信息卡固定宽度，信息展示局促</h3><a id="user-content-14-模型信息卡固定宽度信息展示局促" class="anchor" aria-label="Permalink: 1.4 模型信息卡固定宽度，信息展示局促" href="#14-模型信息卡固定宽度信息展示局促"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">模型名最多 130px，上下文进度条 52px，KV cache 两行小字，整体拥挤。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">1.5 动态背景动画过度</h3><a id="user-content-15-动态背景动画过度" class="anchor" aria-label="Permalink: 1.5 动态背景动画过度" href="#15-动态背景动画过度"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">推理时有扫描线、粒子流、波浪条、呼吸发光、能量脉冲等多层动画叠加，在 92px 高的横栏里分散注意力。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">优化建议：精简 + 分层</h3><a id="user-content-优化建议精简--分层" class="anchor" aria-label="Permalink: 优化建议：精简 + 分层" href="#优化建议精简--分层"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<markdown-accessiblity-table><table>
<thead>
<tr>
<th>优先级</th>
<th>内容</th>
<th>处理方式</th>
</tr>
</thead>
<tbody>
<tr>
<td>P0（常驻）</td>
<td>阶段状态 + TPS + 模型名</td>
<td>永远可见</td>
</tr>
<tr>
<td>P1（常驻）</td>
<td>停止按钮 + 实例切换</td>
<td>永远可见</td>
</tr>
<tr>
<td>P2（按需）</td>
<td>思考模式 / 压缩模式</td>
<td>折叠到菜单或悬停展开</td>
</tr>
<tr>
<td>P3（按需）</td>
<td>上下文使用量 / KV Cache / 进度条</td>
<td>悬停或点击展开详情面板</td>
</tr>
<tr>
<td>P4（低频）</td>
<td>恢复窗口 / 自动隐藏</td>
<td>合并到右键菜单或单按钮</td>
</tr>
</tbody>
</table></markdown-accessiblity-table>
<hr>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">二、主题样式</h2><a id="user-content-二主题样式" class="anchor" aria-label="Permalink: 二、主题样式" href="#二主题样式"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<blockquote>
<p dir="auto">相关文件：<code>vllm-launcher/frontend/src/index.css</code>、<code>vllm-launcher/frontend/src/lib/theme.ts</code></p>
</blockquote>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">2.1 CSS 手动映射维护成本过高</h3><a id="user-content-21-css-手动映射维护成本过高" class="anchor" aria-label="Permalink: 2.1 CSS 手动映射维护成本过高" href="#21-css-手动映射维护成本过高"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">index.css 约 200 行手动 <code>html[data-theme-mode="light"] .text-xxx { color: ... }</code> 映射，每新增颜色类需手动添加覆盖规则，容易遗漏。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">2.2 遗漏的浅色主题覆盖</h3><a id="user-content-22-遗漏的浅色主题覆盖" class="anchor" aria-label="Permalink: 2.2 遗漏的浅色主题覆盖" href="#22-遗漏的浅色主题覆盖"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<markdown-accessiblity-table><table>
<thead>
<tr>
<th>严重性</th>
<th>文件</th>
<th>类名</th>
<th>问题</th>
</tr>
</thead>
<tbody>
<tr>
<td>高</td>
<td>index.css#L97</td>
<td><code>bg-[#050912]</code></td>
<td><code>.terminal-panel</code> 硬编码 hex</td>
</tr>
<tr>
<td>高</td>
<td>DiagnosticCards.tsx</td>
<td><code>bg-black</code></td>
<td>纯黑背景浅色下不可见</td>
</tr>
<tr>
<td>高</td>
<td>Downloads.tsx</td>
<td><code>bg-slate-900/80</code></td>
<td>CSS 仅覆盖 <code>/60</code> 和 <code>/70</code> 变体</td>
</tr>
<tr>
<td>高</td>
<td>Finetune.tsx</td>
<td><code>bg-slate-950</code></td>
<td>无透明度变体未覆盖</td>
</tr>
<tr>
<td>高</td>
<td>FloatingBar.tsx</td>
<td><code>bg-slate-950/95</code></td>
<td>提示框背景未覆盖</td>
</tr>
<tr>
<td>中</td>
<td>InferenceTimeline.tsx</td>
<td><code>bg-slate-800/90</code></td>
<td>CSS 仅覆盖 <code>/40</code>、<code>/60</code>、<code>/80</code></td>
</tr>
<tr>
<td>中</td>
<td>AssistantPanel.tsx</td>
<td><code>border-slate-700</code>、<code>border-slate-600</code></td>
<td>边框浅色下可能消失</td>
</tr>
</tbody>
</table></markdown-accessiblity-table>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">2.3 Modal 遮罩层浅色失效</h3><a id="user-content-23-modal-遮罩层浅色失效" class="anchor" aria-label="Permalink: 2.3 Modal 遮罩层浅色失效" href="#23-modal-遮罩层浅色失效"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">多个组件使用 <code>bg-black/60</code> 遮罩，映射为 <code>var(--app-inset-bg)</code>，浅色主题下变为白色半透明，"压暗"效果完全失效。</p>
<p dir="auto">涉及文件：<code>AddModelDialog.tsx</code>、<code>ControlForm.tsx</code>、<code>ConfirmDialog.tsx</code>、<code>CreateInstanceDialog.tsx</code>、<code>ShutdownDialog.tsx</code></p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">2.4 AssistantPanel 代码块浅色对比度不足</h3><a id="user-content-24-assistantpanel-代码块浅色对比度不足" class="anchor" aria-label="Permalink: 2.4 AssistantPanel 代码块浅色对比度不足" href="#24-assistantpanel-代码块浅色对比度不足"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">AssistantPanel.css 代码块背景浅色下为 <code>#ffffff</code>，与面板背景无区分度；语法高亮无成熟浅色主题。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">2.5 表面类名语义歧义</h3><a id="user-content-25-表面类名语义歧义" class="anchor" aria-label="Permalink: 2.5 表面类名语义歧义" href="#25-表面类名语义歧义"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-css notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=".bg-white\/5 { background-color: var(--app-card-bg, ...); }"><pre>.<span class="pl-c1">bg-white\/</span>5 { <span class="pl-c1">background-color</span><span class="pl-kos">:</span> <span class="pl-en">var</span>(<span class="pl-s1">--app-card-bg</span><span class="pl-kos">,</span> ...); }</pre></div>
<p dir="auto"><code>bg-white/5</code> 暗示白色，实际随主题变化，降低类名可读性。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">2.6 Appearance 页面主题卡片预览对比度不足</h3><a id="user-content-26-appearance-页面主题卡片预览对比度不足" class="anchor" aria-label="Permalink: 2.6 Appearance 页面主题卡片预览对比度不足" href="#26-appearance-页面主题卡片预览对比度不足"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">主题卡片预览区域（48px 高）在浅色主题下 <code>bg-white/5</code> 可能与浅色 deck 渐变对比度不足。</p>
<hr>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">三、Gateway 网关处理</h2><a id="user-content-三gateway-网关处理" class="anchor" aria-label="Permalink: 三、Gateway 网关处理" href="#三gateway-网关处理"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<blockquote>
<p dir="auto">相关文件：<code>launcher/api/routes/gateway.ts</code>、<code>launcher/api/middleware/gatewayLogger.ts</code>、<code>launcher/api/services/gatewayRecorder.ts</code>、<code>launcher/api/services/contextCompressor.ts</code>、<code>launcher/api/routes/anthropicGateway.ts</code></p>
</blockquote>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">3.1 请求体被重复 JSON.parse（P0 性能）</h3><a id="user-content-31-请求体被重复-jsonparsep0-性能" class="anchor" aria-label="Permalink: 3.1 请求体被重复 JSON.parse（P0 性能）" href="#31-请求体被重复-jsonparsep0-性能"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>forwardGatewayRequest</code> 中请求体被解析至少 <strong>8 次</strong>：</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="1. recordRequest → parseJsonSafely
2. truncateOversizedToolResults → JSON.parse
3. compressChatContext → JSON.parse
4. injectReasoningIntoBody → JSON.parse
5. injectStreamOptions → JSON.parse
6. 检测 isStream → JSON.parse
7. 获取 modelName → JSON.parse
8. shouldProcessReasoning → JSON.parse"><pre class="notranslate"><code>1. recordRequest → parseJsonSafely
2. truncateOversizedToolResults → JSON.parse
3. compressChatContext → JSON.parse
4. injectReasoningIntoBody → JSON.parse
5. injectStreamOptions → JSON.parse
6. 检测 isStream → JSON.parse
7. 获取 modelName → JSON.parse
8. shouldProcessReasoning → JSON.parse
</code></pre></div>
<p dir="auto">每次都是 <code>JSON.parse → 处理 → JSON.stringify → 再 parse</code>。大上下文请求（几十 KB ~ MB 级）明显延迟。</p>
<p dir="auto"><strong>建议：</strong> 入口处解析一次，传递 <code>parsedBody: Record&lt;string, unknown&gt;</code> 对象，仅在转发前 stringify 一次。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">3.2 SSE <code>.tee()</code> 双份流处理（P0 性能）</h3><a id="user-content-32-sse-tee-双份流处理p0-性能" class="anchor" aria-label="Permalink: 3.2 SSE .tee() 双份流处理（P0 性能）" href="#32-sse-tee-双份流处理p0-性能"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="const [upstreamForResponse, upstreamForLog] = upstreamReadableStream.tee();"><pre><span class="pl-k">const</span> <span class="pl-kos">[</span><span class="pl-s1">upstreamForResponse</span><span class="pl-kos">,</span> <span class="pl-s1">upstreamForLog</span><span class="pl-kos">]</span> <span class="pl-c1">=</span> <span class="pl-s1">upstreamReadableStream</span><span class="pl-kos">.</span><span class="pl-en">tee</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">每个 byte 被处理两次（日志 + 响应），高 TPS 下翻倍 CPU 和内存。</p>
<p dir="auto"><strong>建议：</strong> 去掉 <code>.tee()</code>，将日志采集合并到主处理管线，单遍处理。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">3.3 路由匹配 O(n) 线性扫描</h3><a id="user-content-33-路由匹配-on-线性扫描" class="anchor" aria-label="Permalink: 3.3 路由匹配 O(n) 线性扫描" href="#33-路由匹配-on-线性扫描"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function findGatewayRouteByModel(modelName) {
  for (const status of getInstanceStatuses()) {  // O(n)
    const aliases = getGatewayAliases(status).map(...);  // 每次都重新生成
    if (aliases.includes(normalized)) { ... }
  }
}"><pre><span class="pl-k">function</span> <span class="pl-en">findGatewayRouteByModel</span><span class="pl-kos">(</span><span class="pl-s1">modelName</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">const</span> <span class="pl-s1">status</span> <span class="pl-k">of</span> <span class="pl-en">getInstanceStatuses</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>  <span class="pl-c">// O(n)</span>
    <span class="pl-k">const</span> <span class="pl-s1">aliases</span> <span class="pl-c1">=</span> <span class="pl-en">getGatewayAliases</span><span class="pl-kos">(</span><span class="pl-s1">status</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">map</span><span class="pl-kos">(</span>...<span class="pl-kos">)</span><span class="pl-kos">;</span>  <span class="pl-c">// 每次都重新生成</span>
    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">aliases</span><span class="pl-kos">.</span><span class="pl-en">includes</span><span class="pl-kos">(</span><span class="pl-s1">normalized</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span> ... <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto"><strong>建议：</strong> 维护 <code>Map&lt;modelAlias, GatewayRouteMatch&gt;</code> 路由表，实例启停时更新，查找 O(1)。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">3.4 Token 估算代码重复</h3><a id="user-content-34-token-估算代码重复" class="anchor" aria-label="Permalink: 3.4 Token 估算代码重复" href="#34-token-估算代码重复"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>estimateTokensFromText</code> 在两个文件中各实现一遍：</p>
<ul dir="auto">
<li><code>gateway.ts</code> 第 588 行</li>
<li><code>contextCompressor.ts</code> 第 49 行</li>
</ul>
<p dir="auto">代码完全相同，维护两份容易不一致。</p>
<p dir="auto"><strong>建议：</strong> 提取到独立的 <code>tokenEstimator.ts</code> 工具模块。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">3.5 gatewayLogger 和 gatewayRecorder 功能重叠</h3><a id="user-content-35-gatewaylogger-和-gatewayrecorder-功能重叠" class="anchor" aria-label="Permalink: 3.5 gatewayLogger 和 gatewayRecorder 功能重叠" href="#35-gatewaylogger-和-gatewayrecorder-功能重叠"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<markdown-accessiblity-table><table>
<thead>
<tr>
<th></th>
<th>gatewayLogger</th>
<th>gatewayRecorder</th>
</tr>
</thead>
<tbody>
<tr>
<td>存储</td>
<td>内存数组（最多 50 条）</td>
<td>磁盘 JSONL（最多 2GB）</td>
</tr>
<tr>
<td>内容</td>
<td>请求头 + 截断 body + SSE preview</td>
<td>完整 rawBody + 响应指标</td>
</tr>
<tr>
<td>用途</td>
<td>调试推理过程</td>
<td>分析 KV Cache / 客户端行为</td>
</tr>
</tbody>
</table></markdown-accessiblity-table>
<p dir="auto">两者各自独立采集相同数据（model、messages、usage 等）。</p>
<p dir="auto"><strong>建议：</strong> 合并为单一录制管线。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">3.6 activeEntry 注册两次 + 类型断言不安全</h3><a id="user-content-36-activeentry-注册两次--类型断言不安全" class="anchor" aria-label="Permalink: 3.6 activeEntry 注册两次 + 类型断言不安全" href="#36-activeentry-注册两次--类型断言不安全"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// 第 819 行（回调内）
registerActiveUpstreamRequest(route.instanceId, activeEntry);
// 第 1035 行（回调外）
registerActiveUpstreamRequest(route.instanceId, activeEntry);"><pre><span class="pl-c">// 第 819 行（回调内）</span>
<span class="pl-en">registerActiveUpstreamRequest</span><span class="pl-kos">(</span><span class="pl-s1">route</span><span class="pl-kos">.</span><span class="pl-c1">instanceId</span><span class="pl-kos">,</span> <span class="pl-s1">activeEntry</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// 第 1035 行（回调外）</span>
<span class="pl-en">registerActiveUpstreamRequest</span><span class="pl-kos">(</span><span class="pl-s1">route</span><span class="pl-kos">.</span><span class="pl-c1">instanceId</span><span class="pl-kos">,</span> <span class="pl-s1">activeEntry</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><strong>建议：</strong> 只在 <code>http.request()</code> 返回后立即注册一次。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">3.7 Anthropic Gateway 兜底路由到第一个实例</h3><a id="user-content-37-anthropic-gateway-兜底路由到第一个实例" class="anchor" aria-label="Permalink: 3.7 Anthropic Gateway 兜底路由到第一个实例" href="#37-anthropic-gateway-兜底路由到第一个实例"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="const targetModel = matched?.modelId ?? instances[0]?.modelId;"><pre><span class="pl-k">const</span> <span class="pl-s1">targetModel</span> <span class="pl-c1">=</span> <span class="pl-s1">matched</span><span class="pl-kos">?.</span><span class="pl-c1">modelId</span> <span class="pl-c1">??</span> <span class="pl-s1">instances</span><span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span><span class="pl-kos">?.</span><span class="pl-c1">modelId</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">匹配失败时静默回退到第一个实例，可能路由到错误模型。</p>
<p dir="auto"><strong>建议：</strong> 返回明确 404 或按能力智能路由。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">3.8 系统代理不走统一管线</h3><a id="user-content-38-系统代理不走统一管线" class="anchor" aria-label="Permalink: 3.8 系统代理不走统一管线" href="#38-系统代理不走统一管线"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">系统代理劫持后走独立的 <code>forwardToGateway</code> 函数，不经过 <code>forwardGatewayRequest</code>，导致上下文压缩、推理处理等功能对代理路径不生效。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">3.9 非流式响应逻辑重复</h3><a id="user-content-39-非流式响应逻辑重复" class="anchor" aria-label="Permalink: 3.9 非流式响应逻辑重复" href="#39-非流式响应逻辑重复"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>reasoningConfig.enabled</code> 和 <code>!enabled</code> 两条路径都调用了 <code>captureInferenceMetrics</code>、<code>recorderSession?.captureUsage</code> 等，逻辑重复。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">3.10 错误处理不精细</h3><a id="user-content-310-错误处理不精细" class="anchor" aria-label="Permalink: 3.10 错误处理不精细" href="#310-错误处理不精细"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">所有上游问题（ECONNREFUSED、ETIMEDOUT、引擎 5xx）都返回 502，客户端无法区分错误类型。</p>
<hr>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">四、模型实例加锁技术</h2><a id="user-content-四模型实例加锁技术" class="anchor" aria-label="Permalink: 四、模型实例加锁技术" href="#四模型实例加锁技术"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<blockquote>
<p dir="auto">相关文件：<code>launcher/api/services/instanceManager.ts</code>、<code>launcher/api/services/presetStore.ts</code>、<code>launcher/api/services/cardMeta.ts</code>、<code>launcher/api/routes/instances.ts</code>、<code>launcher/api/routes/presets.ts</code>、<code>launcher/api/types.ts</code></p>
</blockquote>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">4.1 运行时热切换未受锁保护（P0 安全漏洞）</h3><a id="user-content-41-运行时热切换未受锁保护p0-安全漏洞" class="anchor" aria-label="Permalink: 4.1 运行时热切换未受锁保护（P0 安全漏洞）" href="#41-运行时热切换未受锁保护p0-安全漏洞"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>PATCH /api/instances/:id/runtime/settings</code>（instances.ts 第 275 行）没有锁检查，可修改 reasoning/temperature/topP/stop/maxTokens/compression——这些正是锁要保护的参数。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">4.2 实例启动/停止未受锁保护（P0 安全漏洞）</h3><a id="user-content-42-实例启动停止未受锁保护p0-安全漏洞" class="anchor" aria-label="Permalink: 4.2 实例启动/停止未受锁保护（P0 安全漏洞）" href="#42-实例启动停止未受锁保护p0-安全漏洞"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// 无锁检查
router.post(&quot;/api/instances/:id/stop&quot;, ...)
router.post(&quot;/api/instances/:id/restart&quot;, ...)"><pre><span class="pl-c">// 无锁检查</span>
<span class="pl-s1">router</span><span class="pl-kos">.</span><span class="pl-c1">post</span><span class="pl-kos">(</span><span class="pl-s">"/api/instances/:id/stop"</span><span class="pl-kos">,</span> ...<span class="pl-kos">)</span>
<span class="pl-s1">router</span><span class="pl-kos">.</span><span class="pl-c1">post</span><span class="pl-kos">(</span><span class="pl-s">"/api/instances/:id/restart"</span><span class="pl-kos">,</span> ...<span class="pl-kos">)</span></pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">4.3 <code>isPresetLocked</code> 每次读盘（P1 性能）</h3><a id="user-content-43-ispresetlocked-每次读盘p1-性能" class="anchor" aria-label="Permalink: 4.3 isPresetLocked 每次读盘（P1 性能）" href="#43-ispresetlocked-每次读盘p1-性能"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="export async function isPresetLocked(id: string): Promise&lt;boolean&gt; {
  const data = await readPresets();  // ← 磁盘 IO
  return data.presets.find(...)?.meta?.locked === true;
}"><pre><span class="pl-k">export</span> <span class="pl-k">async</span> <span class="pl-k">function</span> <span class="pl-en">isPresetLocked</span><span class="pl-kos">(</span><span class="pl-s1">id</span>: <span class="pl-smi">string</span><span class="pl-kos">)</span>: <span class="pl-smi">Promise</span><span class="pl-c1">&lt;</span><span class="pl-smi">boolean</span><span class="pl-c1">&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">const</span> <span class="pl-s1">data</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-en">readPresets</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>  <span class="pl-c">// ← 磁盘 IO</span>
  <span class="pl-k">return</span> <span class="pl-s1">data</span><span class="pl-kos">.</span><span class="pl-c1">presets</span><span class="pl-kos">.</span><span class="pl-en">find</span><span class="pl-kos">(</span>...<span class="pl-kos">)</span><span class="pl-kos">?.</span><span class="pl-c1">meta</span><span class="pl-kos">?.</span><span class="pl-c1">locked</span> <span class="pl-c1">===</span> <span class="pl-c1">true</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">而 <code>isInstanceLocked</code> 是纯内存操作。</p>
<p dir="auto"><strong>建议：</strong> 预设数据缓存到内存，锁检查走内存路径。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">4.4 锁检查与操作的 TOCTOU 窗口</h3><a id="user-content-44-锁检查与操作的-toctou-窗口" class="anchor" aria-label="Permalink: 4.4 锁检查与操作的 TOCTOU 窗口" href="#44-锁检查与操作的-toctou-窗口"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">前端先检查锁再执行保存，存在竞态窗口。后端虽有最终拦截，但两套错误提示不一致。</p>
<p dir="auto"><strong>建议：</strong> 前端去掉锁检查，完全依赖后端 403 统一处理。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">4.5 锁粒度单一（仅 boolean）</h3><a id="user-content-45-锁粒度单一仅-boolean" class="anchor" aria-label="Permalink: 4.5 锁粒度单一（仅 boolean）" href="#45-锁粒度单一仅-boolean"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="export type CardMeta = {
  locked: boolean;  // 要么全锁要么全不锁
  // ...
};"><pre><span class="pl-k">export</span> <span class="pl-k">type</span> <span class="pl-smi">CardMeta</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
  <span class="pl-c1">locked</span>: <span class="pl-smi">boolean</span><span class="pl-kos">;</span>  <span class="pl-c">// 要么全锁要么全不锁</span>
  <span class="pl-c">// ...</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><strong>建议：</strong> 扩展为细粒度策略：</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="export type LockPolicy = {
  preventDelete: boolean;
  preventConfigChange: boolean;
  preventLifecycle: boolean;
};"><pre><span class="pl-k">export</span> <span class="pl-k">type</span> <span class="pl-smi">LockPolicy</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
  <span class="pl-c1">preventDelete</span>: <span class="pl-smi">boolean</span><span class="pl-kos">;</span>
  <span class="pl-c1">preventConfigChange</span>: <span class="pl-smi">boolean</span><span class="pl-kos">;</span>
  <span class="pl-c1">preventLifecycle</span>: <span class="pl-smi">boolean</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span></pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">4.6 锁状态变更无审计日志</h3><a id="user-content-46-锁状态变更无审计日志" class="anchor" aria-label="Permalink: 4.6 锁状态变更无审计日志" href="#46-锁状态变更无审计日志"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>updateCardMeta</code> 直接修改内存 + 落盘，无 <code>createInstanceLog</code> 调用。</p>
<p dir="auto"><strong>建议：</strong> 锁状态变更时写实例日志。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">4.7 并发锁写入无保护</h3><a id="user-content-47-并发锁写入无保护" class="anchor" aria-label="Permalink: 4.7 并发锁写入无保护" href="#47-并发锁写入无保护"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">多个请求同时修改同一实例的 meta 和 config 时，锁检查和修改分属不同异步操作，中间可能插入其他请求。</p>
<p dir="auto"><strong>建议：</strong> per-instance 串行化队列。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">4.8 删除路由中锁检查优先于活动状态检查</h3><a id="user-content-48-删除路由中锁检查优先于活动状态检查" class="anchor" aria-label="Permalink: 4.8 删除路由中锁检查优先于活动状态检查" href="#48-删除路由中锁检查优先于活动状态检查"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="if (isInstanceLocked(instanceId)) {  // 先检查锁 → 403
  ...
}
if (status.phase === &quot;running&quot; || ...) {  // 再检查活动 → 409
  ...
}"><pre><span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-en">isInstanceLocked</span><span class="pl-kos">(</span><span class="pl-s1">instanceId</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>  <span class="pl-c">// 先检查锁 → 403</span>
  ...
<span class="pl-kos">}</span>
<span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">status</span><span class="pl-kos">.</span><span class="pl-c1">phase</span> <span class="pl-c1">===</span> <span class="pl-s">"running"</span> <span class="pl-c1">||</span> ...<span class="pl-kos">)</span> <span class="pl-kos">{</span>  <span class="pl-c">// 再检查活动 → 409</span>
  ...
<span class="pl-kos">}</span></pre></div>
<p dir="auto">运行中且加锁的实例返回 403 而非 409，用户困惑。</p>
<p dir="auto"><strong>建议：</strong> 先检查活动状态，再检查锁。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">4.9 锁检查分散，无中间件</h3><a id="user-content-49-锁检查分散无中间件" class="anchor" aria-label="Permalink: 4.9 锁检查分散，无中间件" href="#49-锁检查分散无中间件"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>isPresetLocked</code> 检查分散在 <code>presets.ts</code> 多处，<code>isInstanceLocked</code> 同理，新增路由时容易遗漏。</p>
<p dir="auto"><strong>建议：</strong> 提取为 Express 中间件。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">4.10 锁继承关系未定义</h3><a id="user-content-410-锁继承关系未定义" class="anchor" aria-label="Permalink: 4.10 锁继承关系未定义" href="#410-锁继承关系未定义"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">实例从预设创建时 <code>freshInstanceMeta</code> 总是重置 <code>locked: false</code>，预设加锁后创建的实例默认未加锁，行为合理但无文档说明。</p>
<hr>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">五、进程处理（Go 入口）</h2><a id="user-content-五进程处理go-入口" class="anchor" aria-label="Permalink: 五、进程处理（Go 入口）" href="#五进程处理go-入口"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<blockquote>
<p dir="auto">相关文件：<code>vllm-launcher/main.go</code>、<code>launcher/api/services/instanceLifecycle.ts</code>、<code>launcher/api/services/instanceManager.ts</code>、<code>launcher/api/services/instanceRegistry.ts</code>、<code>launcher/api/services/wslProbe.ts</code></p>
</blockquote>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">5.1 <code>UnrefAllProcesses()</code> 空操作（P0 热退出不可靠）</h3><a id="user-content-51-unrefallprocesses-空操作p0-热退出不可靠" class="anchor" aria-label="Permalink: 5.1 UnrefAllProcesses() 空操作（P0 热退出不可靠）" href="#51-unrefallprocesses-空操作p0-热退出不可靠"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-go notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="func (m *WslManager) UnrefAllProcesses() {
    m.mu.Lock()
    for id, proc := range m.processes {
        log.Printf(&quot;[WSL-MGR] Detaching instance %s&quot;, id, proc.Pid)
    }
    m.mu.Unlock()
}"><pre><span class="pl-k">func</span> (<span class="pl-s1">m</span> <span class="pl-c1">*</span><span class="pl-smi">WslManager</span>) <span class="pl-c1">UnrefAllProcesses</span>() {
    <span class="pl-s1">m</span>.<span class="pl-c1">mu</span>.<span class="pl-c1">Lock</span>()
    <span class="pl-k">for</span> <span class="pl-s1">id</span>, <span class="pl-s1">proc</span> <span class="pl-c1">:=</span> <span class="pl-k">range</span> <span class="pl-s1">m</span>.<span class="pl-c1">processes</span> {
        <span class="pl-s1">log</span>.<span class="pl-c1">Printf</span>(<span class="pl-s">"[WSL-MGR] Detaching instance %s"</span>, <span class="pl-s1">id</span>, <span class="pl-s1">proc</span>.<span class="pl-c1">Pid</span>)
    }
    <span class="pl-s1">m</span>.<span class="pl-c1">mu</span>.<span class="pl-c1">Unlock</span>()
}</pre></div>
<p dir="auto">只打日志，没有设置 <code>proc.Detached = true</code> 或释放 <code>proc.Cmd</code>。Go 进程退出时未 detached 的子进程会被级联杀死，热退出实际上可能杀掉模型。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">5.2 <code>handleStop</code> kill 与 delete 竞态（P0）</h3><a id="user-content-52-handlestop-kill-与-delete-竞态p0" class="anchor" aria-label="Permalink: 5.2 handleStop kill 与 delete 竞态（P0）" href="#52-handlestop-kill-与-delete-竞态p0"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-go notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="go func(pid int) {
    wslCommand(&quot;bash&quot;, &quot;-c&quot;, fmt.Sprintf(&quot;kill %d ...&quot;, pid)).Run()
}(proc.LinuxPid)
delete(m.processes, req.InstanceID)  // 立即删除
json.NewEncoder(w).Encode(StartResponse{Success: true})  // 立即返回"><pre><span class="pl-k">go</span> <span class="pl-k">func</span>(<span class="pl-s1">pid</span> <span class="pl-smi">int</span>) {
    <span class="pl-s1">wslCommand</span>(<span class="pl-s">"bash"</span>, <span class="pl-s">"-c"</span>, <span class="pl-s1">fmt</span>.<span class="pl-c1">Sprintf</span>(<span class="pl-s">"kill %d ..."</span>, <span class="pl-s1">pid</span>)).<span class="pl-c1">Run</span>()
}(<span class="pl-s1">proc</span>.<span class="pl-c1">LinuxPid</span>)
<span class="pl-s1">delete</span>(<span class="pl-s1">m</span>.<span class="pl-c1">processes</span>, <span class="pl-s1">req</span>.<span class="pl-c1">InstanceID</span>)  <span class="pl-c">// 立即删除</span>
<span class="pl-s1">json</span>.<span class="pl-c1">NewEncoder</span>(<span class="pl-s1">w</span>).<span class="pl-c1">Encode</span>(<span class="pl-smi">StartResponse</span>{<span class="pl-s1">Success</span>: <span class="pl-c1">true</span>})  <span class="pl-c">// 立即返回</span></pre></div>
<p dir="auto">Kill 异步执行，Map 立即删除，响应立即返回。此时进程可能还在运行，端口仍被占用。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">5.3 Node.js 自动重启无上限（P1）</h3><a id="user-content-53-nodejs-自动重启无上限p1" class="anchor" aria-label="Permalink: 5.3 Node.js 自动重启无上限（P1）" href="#53-nodejs-自动重启无上限p1"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-go notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="restartCount := 0
for {
    cmd.Wait()
    restartCount++
    // 无上限，无限重启
}"><pre><span class="pl-s1">restartCount</span> <span class="pl-c1">:=</span> <span class="pl-c1">0</span>
<span class="pl-k">for</span> {
    <span class="pl-s1">cmd</span>.<span class="pl-c1">Wait</span>()
    <span class="pl-s1">restartCount</span><span class="pl-c1">++</span>
    <span class="pl-c">// 无上限，无限重启</span>
}</pre></div>
<p dir="auto"><code>server.cjs</code> 启动错误时无限重启，每秒 2 次。</p>
<p dir="auto"><strong>建议：</strong> 添加上限（10 次）或退避策略。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">5.4 Go 与 Node.js 进程跟踪双重管理（P1）</h3><a id="user-content-54-go-与-nodejs-进程跟踪双重管理p1" class="anchor" aria-label="Permalink: 5.4 Go 与 Node.js 进程跟踪双重管理（P1）" href="#54-go-与-nodejs-进程跟踪双重管理p1"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<markdown-accessiblity-table><table>
<thead>
<tr>
<th>跟踪方</th>
<th>存储</th>
<th>更新时机</th>
</tr>
</thead>
<tbody>
<tr>
<td>Go WSL Manager</td>
<td><code>wslMgr.processes</code> Map</td>
<td>启动/停止/PID 更新</td>
</tr>
<tr>
<td>Node.js</td>
<td><code>activeProcesses</code> + <code>instanceLinuxPids</code> + <code>instanceStatuses</code></td>
<td>启动/日志解析/对账</td>
</tr>
</tbody>
</table></markdown-accessiblity-table>
<p dir="auto">两者通过 HTTP 通信，无一致性保证，可能出现状态不一致。</p>
<p dir="auto"><strong>建议：</strong> 明确单一事实来源。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">5.5 Linux PID 通过日志正则解析获取（P2）</h3><a id="user-content-55-linux-pid-通过日志正则解析获取p2" class="anchor" aria-label="Permalink: 5.5 Linux PID 通过日志正则解析获取（P2）" href="#55-linux-pid-通过日志正则解析获取p2"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">依赖日志轮询（2 秒间隔）+ 正则匹配提取 PID，Go 侧等待 5 秒，最坏 7 秒内 PID 未知。</p>
<p dir="auto"><strong>建议：</strong> 引擎启动脚本将 PID 写入 <code>/tmp/{instanceId}.pid</code> 文件。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">5.6 健康探测四层串行，最坏 32 秒/实例（P2）</h3><a id="user-content-56-健康探测四层串行最坏-32-秒实例p2" class="anchor" aria-label="Permalink: 5.6 健康探测四层串行，最坏 32 秒/实例（P2）" href="#56-健康探测四层串行最坏-32-秒实例p2"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="第0层: Go WSL Manager check (5s timeout)
第1层: Linux PID kill -0 (5s timeout)
第2层: WSL curl (12s timeout)
第3层: Windows → WSL HTTP fetch (5s × 2)"><pre class="notranslate"><code>第0层: Go WSL Manager check (5s timeout)
第1层: Linux PID kill -0 (5s timeout)
第2层: WSL curl (12s timeout)
第3层: Windows → WSL HTTP fetch (5s × 2)
</code></pre></div>
<p dir="auto"><strong>建议：</strong> 第 1 层和第 2 层并行，去掉第 0 层。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">5.7 对账循环 20 秒间隔，崩溃发现延迟高（P2）</h3><a id="user-content-57-对账循环-20-秒间隔崩溃发现延迟高p2" class="anchor" aria-label="Permalink: 5.7 对账循环 20 秒间隔，崩溃发现延迟高（P2）" href="#57-对账循环-20-秒间隔崩溃发现延迟高p2"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">模型进程崩溃后最多 20 秒界面才从 running 变为 error，期间网关请求均 502。</p>
<p dir="auto"><strong>建议：</strong> 网关 ECONNREFUSED 时立即触发对该实例的对账。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">5.8 <code>cmd.Wait()</code> goroutine 泄漏（P2）</h3><a id="user-content-58-cmdwait-goroutine-泄漏p2" class="anchor" aria-label="Permalink: 5.8 cmd.Wait() goroutine 泄漏（P2）" href="#58-cmdwait-goroutine-泄漏p2"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">频繁启动→停止→启动同一实例，每次 <code>cmd.Start()</code> 产生新的 <code>Wait()</code> goroutine，旧的在 <code>Process.Kill()</code> 后才退出，持有 <code>cmd</code> 引用阻止 GC。</p>
<p dir="auto"><strong>建议：</strong> 用 <code>context.WithCancel</code> 替代。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">5.9 孤儿进程扫描正则过于宽松（P2）</h3><a id="user-content-59-孤儿进程扫描正则过于宽松p2" class="anchor" aria-label="Permalink: 5.9 孤儿进程扫描正则过于宽松（P2）" href="#59-孤儿进程扫描正则过于宽松p2"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="if (/vllm serve|vllm\.entrypoints/.test(args)) engineType = &quot;vllm&quot;;"><pre><span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-pds"><span class="pl-c1">/</span><span class="pl-s">v</span><span class="pl-s">l</span><span class="pl-s">l</span><span class="pl-s">m</span><span class="pl-s"> </span><span class="pl-s">s</span><span class="pl-s">e</span><span class="pl-s">r</span><span class="pl-s">v</span><span class="pl-s">e</span><span class="pl-c1">|</span><span class="pl-s">v</span><span class="pl-s">l</span><span class="pl-s">l</span><span class="pl-s">m</span><span class="pl-cce">\.</span><span class="pl-s">e</span><span class="pl-s">n</span><span class="pl-s">t</span><span class="pl-s">r</span><span class="pl-s">y</span><span class="pl-s">p</span><span class="pl-s">o</span><span class="pl-s">i</span><span class="pl-s">n</span><span class="pl-s">t</span><span class="pl-s">s</span><span class="pl-c1">/</span></span><span class="pl-kos">.</span><span class="pl-en">test</span><span class="pl-kos">(</span><span class="pl-s1">args</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-s1">engineType</span> <span class="pl-c1">=</span> <span class="pl-s">"vllm"</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><code>ps -eo pid=,etimes=args</code> 输出可能匹配到非引擎进程。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">5.10 WSL2 Heartbeat 无条件运行（P2）</h3><a id="user-content-510-wsl2-heartbeat-无条件运行p2" class="anchor" aria-label="Permalink: 5.10 WSL2 Heartbeat 无条件运行（P2）" href="#510-wsl2-heartbeat-无条件运行p2"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">每 3 分钟执行 <code>wsl.exe --exec true</code>，无模型时也运行，WSL 关闭时自动唤醒 VM。</p>
<p dir="auto"><strong>建议：</strong> 仅在存在运行中实例时启用。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">5.11 <code>stopNodeServer()</code> 直接 Kill（P2）</h3><a id="user-content-511-stopnodeserver-直接-killp2" class="anchor" aria-label="Permalink: 5.11 stopNodeServer() 直接 Kill（P2）" href="#511-stopnodeserver-直接-killp2"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-go notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="a.nodeCmd.Process.Kill()  // 直接 SIGKILL"><pre><span class="pl-s1">a</span>.<span class="pl-c1">nodeCmd</span>.<span class="pl-c1">Process</span>.<span class="pl-c1">Kill</span>()  <span class="pl-c">// 直接 SIGKILL</span></pre></div>
<p dir="auto">Node.js 无机会执行清理逻辑（录制落盘、索引刷新等）。</p>
<p dir="auto"><strong>建议：</strong> 先 SIGTERM，等待后 Kill。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">5.12 重启流程无事务语义（P2）</h3><a id="user-content-512-重启流程无事务语义p2" class="anchor" aria-label="Permalink: 5.12 重启流程无事务语义（P2）" href="#512-重启流程无事务语义p2"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>stopInstance</code> 成功后 <code>startInstance</code> 失败，实例处于不一致状态。</p>
<hr>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">六、字体和颜色</h2><a id="user-content-六字体和颜色" class="anchor" aria-label="Permalink: 六、字体和颜色" href="#六字体和颜色"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<blockquote>
<p dir="auto">相关文件：<code>vllm-launcher/frontend/src/index.css</code>、<code>vllm-launcher/frontend/src/lib/theme.ts</code>、<code>vllm-launcher/frontend/src/components/AssistantPanel.css</code>、<code>vllm-launcher/frontend/tailwind.config.js</code></p>
</blockquote>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">6.1 Google Fonts 在线依赖（P0）</h3><a id="user-content-61-google-fonts-在线依赖p0" class="anchor" aria-label="Permalink: 6.1 Google Fonts 在线依赖（P0）" href="#61-google-fonts-在线依赖p0"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-css notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@import url(&quot;https://fonts.googleapis.com/css2?family=Chakra+Petch&amp;family=IBM+Plex+Mono&amp;family=Manrope&amp;display=swap&quot;);"><pre><span class="pl-k">@import</span> <span class="pl-en">url</span>(<span class="pl-s">"https://fonts.googleapis.com/css2?family=Chakra+Petch&amp;family=IBM+Plex+Mono&amp;family=Manrope&amp;display=swap"</span>);</pre></div>
<p dir="auto">国内被墙，超时 10-30 秒，首屏渲染延迟。</p>
<p dir="auto"><strong>建议：</strong> 字体文件下载到本地，用 <code>@font-face</code> + <code>embed</code> 打包进应用。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">6.2 AssistantPanel px 字号不跟随缩放（P0）</h3><a id="user-content-62-assistantpanel-px-字号不跟随缩放p0" class="anchor" aria-label="Permalink: 6.2 AssistantPanel px 字号不跟随缩放（P0）" href="#62-assistantpanel-px-字号不跟随缩放p0"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">AssistantPanel.css 中 9 处 <code>px</code> 字号（<code>13px</code>、<code>12px</code>、<code>11px</code>），Ctrl+滚轮缩放根字号时助手面板 Markdown 内容不跟随。</p>
<p dir="auto"><strong>建议：</strong> <code>px</code> → <code>rem</code>（13px=0.929rem, 12px=0.857rem, 11px=0.786rem）。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">6.3 Modal 遮罩浅色失效（P0）</h3><a id="user-content-63-modal-遮罩浅色失效p0" class="anchor" aria-label="Permalink: 6.3 Modal 遮罩浅色失效（P0）" href="#63-modal-遮罩浅色失效p0"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>bg-black/60</code> 映射为 <code>var(--app-inset-bg)</code>，浅色主题下为 <code>rgba(255,255,255,0.60)</code>，失去"压暗"效果。</p>
<p dir="auto"><strong>建议：</strong> 独立 <code>.modal-overlay</code> 类，浅色下用 <code>bg-slate-900/30</code> + <code>backdrop-blur-sm</code>。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">6.4 浅色主题 150 行手动映射（P1）</h3><a id="user-content-64-浅色主题-150-行手动映射p1" class="anchor" aria-label="Permalink: 6.4 浅色主题 150 行手动映射（P1）" href="#64-浅色主题-150-行手动映射p1"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">index.css 约 150 行 <code>html[data-theme-mode="light"] .text-xxx</code> 手动覆盖，新增页面易遗漏。</p>
<p dir="auto"><strong>建议：</strong> Tailwind 配置中扩展颜色 palette 或使用 CSS 变量 + <code>color-mix()</code>。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">6.5 SparkLineChart 硬编码 hex（P1）</h3><a id="user-content-65-sparklinechart-硬编码-hexp1" class="anchor" aria-label="Permalink: 6.5 SparkLineChart 硬编码 hex（P1）" href="#65-sparklinechart-硬编码-hexp1"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="color: &quot;#3AE3D6&quot;  // 深色清晰，浅色隐形
color: &quot;#34D399&quot;
color: &quot;#F59E0B&quot;  // 浅色对比度不足"><pre>color: <span class="pl-s">"#3AE3D6"</span>  <span class="pl-c">// 深色清晰，浅色隐形</span>
color: <span class="pl-s">"#34D399"</span>
color: <span class="pl-s">"#F59E0B"</span>  <span class="pl-c">// 浅色对比度不足</span></pre></div>
<p dir="auto"><strong>建议：</strong> 用 Tailwind 颜色类或 CSS 变量。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">6.6 Tailwind 未自定义主题色（P1）</h3><a id="user-content-66-tailwind-未自定义主题色p1" class="anchor" aria-label="Permalink: 6.6 Tailwind 未自定义主题色（P1）" href="#66-tailwind-未自定义主题色p1"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">tailwind.config.js 完全使用默认配置，无法用 <code>bg-card</code>、<code>text-primary</code> 等语义化类名。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">6.7 主题切换闪烁（P1）</h3><a id="user-content-67-主题切换闪烁p1" class="anchor" aria-label="Permalink: 6.7 主题切换闪烁（P1）" href="#67-主题切换闪烁p1"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">CSS 变量先设置，<code>data-theme-mode</code> 后设置，中间出现半深色半浅色状态。</p>
<p dir="auto"><strong>建议：</strong> 先设置 <code>data-theme-mode</code>，再设置 CSS 变量。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">6.8 字体选择稀少（P2）</h3><a id="user-content-68-字体选择稀少p2" class="anchor" aria-label="Permalink: 6.8 字体选择稀少（P2）" href="#68-字体选择稀少p2"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">仅 4 种字体（系统默认、微软雅黑、等线、黑体），无英文/代码友好字体，黑体不支持字重变化（合成粗体模糊）。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">6.9 等宽字体回退链不一致（P2）</h3><a id="user-content-69-等宽字体回退链不一致p2" class="anchor" aria-label="Permalink: 6.9 等宽字体回退链不一致（P2）" href="#69-等宽字体回退链不一致p2"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">终端面板用 <code>IBM Plex Mono, monospace</code>，代码块用 <code>ui-monospace, Cascadia Mono, Consolas, monospace</code>，离线时字体不同。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">6.10 滚动条浅色对比度不足（P2）</h3><a id="user-content-610-滚动条浅色对比度不足p2" class="anchor" aria-label="Permalink: 6.10 滚动条浅色对比度不足（P2）" href="#610-滚动条浅色对比度不足p2"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">浅色下 <code>rgba(100, 116, 139, 0.45)</code> 仍然偏淡。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">6.11 根元素文字颜色硬编码（P2）</h3><a id="user-content-611-根元素文字颜色硬编码p2" class="anchor" aria-label="Permalink: 6.11 根元素文字颜色硬编码（P2）" href="#611-根元素文字颜色硬编码p2"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-css notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=":root { color: #edf7ff; }  /* 固定值，非 CSS 变量 */"><pre><span class="pl-kos">:</span><span class="pl-c1">root</span> { <span class="pl-c1">color</span><span class="pl-kos">:</span> <span class="pl-pds"><span class="pl-kos">#</span>edf7ff</span>; }  <span class="pl-c">/* 固定值，非 CSS 变量 */</span></pre></div>
<p dir="auto">新增主题时文字色可能不匹配背景。</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">6.12 <code>auto</code> 主题 <code>mode</code> 固定为 <code>"dark"</code>（P2）</h3><a id="user-content-612-auto-主题-mode-固定为-darkp2" class="anchor" aria-label="Permalink: 6.12 auto 主题 mode 固定为 &quot;dark&quot;（P2）" href="#612-auto-主题-mode-固定为-darkp2"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>data-theme-mode</code> 标记与实际渲染不一致，依赖 <code>applyThemeSettings</code> 延迟修正，可能出现闪烁。</p>
<hr>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">全局优先级汇总</h2><a id="user-content-全局优先级汇总" class="anchor" aria-label="Permalink: 全局优先级汇总" href="#全局优先级汇总"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<markdown-accessiblity-table><table>
<thead>
<tr>
<th>优先级</th>
<th>问题数</th>
<th>涉及模块</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>P0</strong></td>
<td>8</td>
<td>悬浮窗、主题、Gateway、加锁、进程、字体颜色</td>
</tr>
<tr>
<td><strong>P1</strong></td>
<td>10</td>
<td>Gateway、加锁、进程、字体颜色</td>
</tr>
<tr>
<td><strong>P2</strong></td>
<td>20+</td>
<td>全模块</td>
</tr>
</tbody>
</table></markdown-accessiblity-table>
</article></div><div class="d-none"></div></section></div></div></div> </div> <!-- --> </div></div></div></div></div></div><div class="ScrollMarksContainer-module__scrollMarksContainer__Eu7uU" id="find-result-marks-container"></div><div class="d-none"></div><div class="d-none"></div></div> <!-- --> <!-- --> </div>
</react-app>




  </div>

</turbo-frame>

    </main>
  </div>

  </div>

          <footer class="footer f6 color-fg-muted color-border-subtle tmp-pt-7 tmp-pb-6 p-responsive" role="contentinfo"  >
  <h2 class='sr-only'>Footer</h2>

  


  <div class="d-flex flex-justify-center flex-items-center flex-column-reverse flex-lg-row flex-wrap flex-lg-nowrap">
    <div class="d-flex flex-items-center flex-shrink-0 mx-2">
      <a aria-label="GitHub Homepage" class="footer-octicon mr-2" href="https://github.com">
        <svg aria-hidden="true" data-component="Octicon" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-mark-github">
    <path d="M10.226 17.284c-2.965-.36-5.054-2.493-5.054-5.256 0-1.123.404-2.336 1.078-3.144-.292-.741-.247-2.314.09-2.965.898-.112 2.111.36 2.83 1.01.853-.269 1.752-.404 2.853-.404 1.1 0 1.999.135 2.807.382.696-.629 1.932-1.1 2.83-.988.315.606.36 2.179.067 2.942.72.854 1.101 2 1.101 3.167 0 2.763-2.089 4.852-5.098 5.234.763.494 1.28 1.572 1.28 2.807v2.336c0 .674.561 1.056 1.235.786 4.066-1.55 7.255-5.615 7.255-10.646C23.5 6.188 18.334 1 11.978 1 5.62 1 .5 6.188.5 12.545c0 4.986 3.167 9.12 7.435 10.669.606.225 1.19-.18 1.19-.786V20.63a2.9 2.9 0 0 1-1.078.224c-1.483 0-2.359-.808-2.987-2.313-.247-.607-.517-.966-1.034-1.033-.27-.023-.359-.135-.359-.27 0-.27.45-.471.898-.471.652 0 1.213.404 1.797 1.235.45.651.921.943 1.483.943.561 0 .92-.202 1.437-.719.382-.381.674-.718.944-.943"></path>
</svg>
</a>
      <span>
        &copy; 2026 GitHub,&nbsp;Inc.
      </span>
    </div>

    <nav aria-label="Footer">
      <h3 class="sr-only" id="sr-footer-heading">Footer navigation</h3>

      <ul class="list-style-none d-flex flex-justify-center flex-wrap mb-2 mb-lg-0" aria-labelledby="sr-footer-heading">


          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to Terms&quot;,&quot;label&quot;:&quot;text:terms&quot;}" href="https://docs.github.com/site-policy/github-terms/github-terms-of-service" data-view-component="true" class="Link--secondary Link">Terms</a>
          </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to privacy&quot;,&quot;label&quot;:&quot;text:privacy&quot;}" href="https://docs.github.com/site-policy/privacy-policies/github-privacy-statement" data-view-component="true" class="Link--secondary Link">Privacy</a>
          </li>


            <li class="mx-2">
              <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to security&quot;,&quot;label&quot;:&quot;text:security&quot;}" href="https://github.com/security" data-view-component="true" class="Link--secondary Link">Security</a>
            </li>

            <li class="mx-2">
              <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to status&quot;,&quot;label&quot;:&quot;text:status&quot;}" href="https://www.githubstatus.com/" data-view-component="true" class="Link--secondary Link">Status</a>
            </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to community&quot;,&quot;label&quot;:&quot;text:community&quot;}" href="https://github.community/" data-view-component="true" class="Link--secondary Link">Community</a>
          </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to docs&quot;,&quot;label&quot;:&quot;text:docs&quot;}" href="https://docs.github.com/" data-view-component="true" class="Link--secondary Link">Docs</a>
          </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to contact&quot;,&quot;label&quot;:&quot;text:contact&quot;}" href="https://support.github.com?tags=dotcom-footer" data-view-component="true" class="Link--secondary Link">Contact</a>
          </li>

          
<li class="mx-2" >
  <cookie-consent-link>
    <button
      type="button"
      class="Link--secondary underline-on-hover border-0 p-0 color-bg-transparent"
      data-action="click:cookie-consent-link#showConsentManagement"
      data-analytics-event="{&quot;location&quot;:&quot;footer&quot;,&quot;action&quot;:&quot;cookies&quot;,&quot;context&quot;:&quot;subfooter&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;cookies_link_subfooter_footer&quot;}"
    >
      Manage cookies
    </button>
  </cookie-consent-link>
</li>

  <li class="mx-2">
    <cookie-consent-link>
      <button
        type="button"
        class="Link--secondary underline-on-hover border-0 p-0 color-bg-transparent text-left"
        data-action="click:cookie-consent-link#showConsentManagement"
        data-analytics-event="{&quot;location&quot;:&quot;footer&quot;,&quot;action&quot;:&quot;dont_share_info&quot;,&quot;context&quot;:&quot;subfooter&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;dont_share_info_link_subfooter_footer&quot;}"
      >
        Do not share my personal information
      </button>
    </cookie-consent-link>
  </li>

      </ul>
    </nav>
  </div>
</footer>



    <ghcc-consent id="ghcc" class="position-fixed bottom-0 left-0" style="z-index: 999999"
      data-locale="en"
      data-initial-cookie-consent-allowed=""
      data-cookie-consent-required="true"
    ></ghcc-consent>




  <div id="ajax-error-message" class="ajax-error-message flash flash-error" hidden>
    <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert">
    <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
    <button type="button" class="flash-close js-ajax-error-dismiss" aria-label="Dismiss error">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
    </button>
    You can’t perform that action at this time.
  </div>

    <template id="site-details-dialog">
  <details class="details-reset details-overlay details-overlay-dark lh-default color-fg-default hx_rsm" open>
    <summary role="button" aria-label="Close dialog"></summary>
    <details-dialog class="Box Box--overlay d-flex flex-column anim-fade-in fast hx_rsm-dialog hx_rsm-modal">
      <button class="Box-btn-octicon m-0 btn-octicon position-absolute right-0 top-0" type="button" aria-label="Close dialog" data-close-dialog>
        <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
      </button>
      <div class="octocat-spinner tmp-my-6 js-details-dialog-spinner"></div>
    </details-dialog>
  </details>
</template>

    <div class="Popover js-hovercard-content position-absolute" style="display: none; outline: none;">
  <div class="Popover-message Popover-message--bottom-left Popover-message--large Box color-shadow-large" style="width:360px;">
  </div>
</div>

    <template id="snippet-clipboard-copy-button">
  <div class="zeroclipboard-container position-absolute right-0 top-0">
    <clipboard-copy aria-label="Copy code to clipboard" class="ClipboardButton btn js-clipboard-copy m-2 p-0" data-copy-feedback="Copied!" data-tooltip-direction="w">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copy js-clipboard-copy-icon m-2 tmp-m-2">
    <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path>
</svg>
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-check js-clipboard-check-icon color-fg-success d-none m-2 tmp-m-2">
    <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path>
</svg>
    </clipboard-copy>
  </div>
</template>
<template id="snippet-clipboard-copy-button-unpositioned">
  <div class="zeroclipboard-container">
    <clipboard-copy aria-label="Copy code to clipboard" class="ClipboardButton btn btn-invisible js-clipboard-copy m-2 p-0 d-flex flex-justify-center flex-items-center" data-copy-feedback="Copied!" data-tooltip-direction="w">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copy js-clipboard-copy-icon">
    <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path>
</svg>
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-check js-clipboard-check-icon color-fg-success d-none">
    <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path>
</svg>
    </clipboard-copy>
  </div>
</template>




    </div>
    <div id="js-global-screen-reader-notice" class="sr-only mt-n1" aria-live="polite" aria-atomic="true" ></div>
    <div id="js-global-screen-reader-notice-assertive" class="sr-only mt-n1" aria-live="assertive" aria-atomic="true"></div>
  </body>
</html>

