



  

<!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-7a418ea859d1654d.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","activity_diff_file_tree","activity_repos_file_tree","activity_repos_overview_header","activity_repos_overview_sidebar","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_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_workbench_sunset_redirect","dashboard_agents_module_auth_token_check","dashboard_indexeddb_caching","dashboard_lists_max_age_filter","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","issues_expanded_file_types","issues_hide_closed_sub_issues","issues_index_data_router","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","milestone_show_data_router","octocaptcha_origin_optimization","primer_react_css_anchor_positioning","primer_react_merged_forwarded_refs","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","repo_pulls_dashboard_sidebar_links","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-b752d992928a526c.js"></script>
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/wp-runtime-3d724f91bb12ac15.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/app-foundation-2f08c823163591a8.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/app-runtime-633ad94fa06c334b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/fetch-utilities-0fb4c544a797ec0d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ser-7c872b58ac9f1b39.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/tp-7e9817cf5c068979.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/environment-e2c7d9b56ea85c83.js" defer="defer"></script>
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/app-runtime.bef03fb24bb03be8.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-0417f617ad744a0d.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-f1498fec45311acd.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/jz5-7aa1ff0a0e750f41.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-9697c1c8f5cbf523.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/github-elements-f48dde857ba079b2.js" defer="defer"></script>
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/element-registry-5ca1990512ce9293.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-524a06aa946df6fc.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hotkey-b1ee53c2200b172a.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-core-7bf7b9d689fe3d10.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/a9-ca3bc10b816bcc1f.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ur-21ec1e439ee2d87c.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/4t-4c39f7195fc42cc8.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/pb-53cfff089eaac51b.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-4d9cf83cf08e1643.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/wo-6991af5b3829ffe8.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/nfv-a6c14301d3ea6d67.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/b5-a2fde30ce0c692b9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/sw-9d0489dbf9a9c942.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ttf-7d5abe1b447ced2c.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/sj-c7a44023ee90d468.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/0pd-c46d8dfae89c2b64.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/behaviors-c2c2df50a7f31171.js" defer="defer"></script>
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/react-core.255cab819a92f7e1.module.css" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/code-menu-ed075240458e4b06.js" defer="defer"></script>
  
  <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/primer-react-8503588299651923.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ncx-66e64888bc4615bb.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-a9404625ec30bbc7.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/4u-8f9f1d6be01d6a22.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/s0-68d09e5e8a80cb94.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/y5-0cb3f75cec297941.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/n4u-cd9039ad946274ad.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j8s-00bd469c4017a543.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-2d03f5e6d4fdd54d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/gru-2b0fac8887ff8c57.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/a0-234e967e7c6d22ce.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/gz3-5bdfbfceac967bb6.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/15m-64f3034430471048.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/1e-c15441bdb94d54ae.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/gzu-6ad9a0527a5d7afd.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/bi-3a42b8714e06c4d0.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/tu1-37e16844272ddefa.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/b1-ac66ededed061993.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/gmn-1e5497c041b66231.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/0l5-d1b2a63015b5eb6d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/c2-e85522be441acf73.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/f9-baf0a4193779952e.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/sp-87dce99c82a27004.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/zkm-116b01b8485bbe3f.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/og-518d12c9e011601d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/b9-947db365ea875cfa.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/14-8c7b4ad3c845664c.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/dsj-2e7d883cb843e9e6.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ec-38012819307fd539.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/du-6607da3b8b579202.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/20-f43eb09c2be69457.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ql0-107312645ac2b72d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/wp-fa7cdc0f7656d876.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/p0l-fe491d943adf7508.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/v1e-d099d9fd21ad25e5.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/fn-7b298a45c55fb6fb.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/7cw-6e493a20eaaa04b5.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ok-290e4b9465ba9c5b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/6d-ca6d584a0fd6368c.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/y8-e2f18f5a24733f3b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/xc-3fd4a2e7dcbad8e2.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/vjg-2874f95f389c4d3f.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/code-view-7ebc2e6daa7c8336.js" defer="defer"></script>
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.e4334163c54cccf5.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/ql0.501e99879e15a48e.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/xc.de2b1dde0494f261.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/code-view.fe8185756c08c07d.module.css" />


  <title>nullclaw/docs/integration-analysis.md at main · nullclaw/nullclaw · 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:3638fb8e-9a82-4aed-c159-683dfd5aec69">

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


  <meta name="request-id" content="D312:259F5:3FF330:4FA042:6AC78936" data-pjax-transient="true"/><meta name="html-safe-nonce" content="10f188ae6e5ff569d2474fa9645df70c8ab7f567eafda77929d45ab6a12ad58f" data-pjax-transient="true"/><meta name="visitor-payload" content="eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJEMzEyOjI1OUY1OjNGRjMzMDo0RkEwNDI6NkFDNzg5MzYiLCJ2aXNpdG9yX2lkIjoiOTA0ODcwODU0MjQzMzU0OTM0IiwicmVnaW9uX2VkZ2UiOiJmcmEiLCJyZWdpb25fcmVuZGVyIjoiZnJhIn0=" data-pjax-transient="true"/><meta name="visitor-hmac" content="8898a3dab7897e4e73c263fbbcb1dda19a656ba01ef60f604b1516125c7a0e3f" data-pjax-transient="true"/>


    <meta name="hovercard-subject-tag" content="repository:1159542259" 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="Fastest, smallest, and fully autonomous AI assistant infrastructure written in Zig - nullclaw/docs/integration-analysis.md at main · nullclaw/nullclaw">

      <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/nullclaw/nullclaw/blob/main/docs/integration-analysis.md" />

      <meta name="twitter:image" content="https://opengraph.githubassets.com/825ecff44ab681b9ae11f51319588e3ddbfb705fcbe54c1abca37e242ee4b628/nullclaw/nullclaw" /><meta name="twitter:site" content="@github" /><meta name="twitter:card" content="summary_large_image" /><meta name="twitter:title" content="nullclaw/docs/integration-analysis.md at main · nullclaw/nullclaw" /><meta name="twitter:description" content="Fastest, smallest, and fully autonomous AI assistant infrastructure written in Zig - nullclaw/nullclaw" />
  <meta property="og:image" content="https://opengraph.githubassets.com/825ecff44ab681b9ae11f51319588e3ddbfb705fcbe54c1abca37e242ee4b628/nullclaw/nullclaw" /><meta property="og:image:alt" content="Fastest, smallest, and fully autonomous AI assistant infrastructure written in Zig - nullclaw/nullclaw" /><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="nullclaw/docs/integration-analysis.md at main · nullclaw/nullclaw" /><meta property="og:url" content="https://github.com/nullclaw/nullclaw/blob/main/docs/integration-analysis.md" /><meta property="og:description" content="Fastest, smallest, and fully autonomous AI assistant infrastructure written in Zig - nullclaw/nullclaw" />
  




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



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


  <meta http-equiv="x-pjax-version" content="5ae8b4ba8a4be23b638a948af46d4760710b9eeafaeef8ffd3a066a87f439cab" 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="1ff3f1d4e1abd61f6f135b47d3b815e2f7169f8dd418f0118c6b1cf4de6cbc86" data-turbo-track="reload">
  <meta http-equiv="x-pjax-js-version" content="7c762ef82adaf98b9fbb02482b925ff53c4dd7b1778a6dffac62ffb579b37c39" 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/nullclaw/nullclaw git https://github.com/nullclaw/nullclaw.git">

  <meta name="octolytics-dimension-user_id" content="262007611" /><meta name="octolytics-dimension-user_login" content="nullclaw" /><meta name="octolytics-dimension-repository_id" content="1159542259" /><meta name="octolytics-dimension-repository_nwo" content="nullclaw/nullclaw" /><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="1159542259" /><meta name="octolytics-dimension-repository_network_root_nwo" content="nullclaw/nullclaw" />
  



    

    <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="acf81f254b225f7dd3493ed02d8bd168abfffbf4" 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/qc-1bbbe8787ea1cd4b.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/keyboard-shortcuts-dialog-79183764d9db225c.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.e4334163c54cccf5.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/keyboard-shortcuts-dialog.3158a73a95382d59.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-46deaef4fa9abcf6.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.e4334163c54cccf5.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/app-install-banner-partial.afb275bc17fddee0.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/2l-e468179ba7123a2e.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/rwd-069fc3d9814ff9fe.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/fz-e662bc3745e171e7.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/jag-3559ee48016881a2.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/3d-7f22b36f29a9dd94.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/tua-4998592d21eb16f7.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/8i-756d611a52e5f265.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/marketing-header-30705a8b2a0dea92.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.e4334163c54cccf5.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-brand-css.05b219cdb8e80c43.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/8i.779dd52a6bc5b0b6.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%2Fnullclaw%2Fnullclaw%2Fblob%2Fmain%2Fdocs%2Fintegration-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=nullclaw%2Fnullclaw","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/nullclaw/nullclaw/blob/main/docs/integration-analysis.md\",\"user_id\":null}}","auth_hydro_click_hmac":"20da92af2ca78f70885aac824e32689721a9448c6178c366870ae39ba395d393","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%2Fnullclaw%2Fnullclaw%2Fblob%2Fmain%2Fdocs%2Fintegration-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/nullclaw/nullclaw/blob/main/docs/integration-analysis.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="20da92af2ca78f70885aac824e32689721a9448c6178c366870ae39ba395d393"><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%2Fnullclaw%2Fnullclaw%2Fblob%2Fmain%2Fdocs%2Fintegration-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/nullclaw/nullclaw/blob/main/docs/integration-analysis.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="20da92af2ca78f70885aac824e32689721a9448c6178c366870ae39ba395d393"><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=nullclaw%2Fnullclaw" 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/nullclaw/nullclaw/blob/main/docs/integration-analysis.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="20da92af2ca78f70885aac824e32689721a9448c6178c366870ae39ba395d393"><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-bf7b2e61-bef7-4a07-b487-e9e2b2193b80" aria-labelledby="tooltip-6af89875-6796-49f4-a447-5db27e33e7a9" 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-6af89875-6796-49f4-a447-5db27e33e7a9" for="icon-button-bf7b2e61-bef7-4a07-b487-e9e2b2193b80" 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-1a7ce813a378e1f7.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/mn-bb458474353a279e.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/t5-26d19272bbf73ca3.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/2d5-9abb2f6ba5c935d0.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/24-b11e1c4108322883.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/mrn-12afac2ecd2be980.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/dgq-bbf7670f9cdba2e0.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/7w-740b4e942974ccba.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/we-c9f93392098ad6c9.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/775-5adcc74216a7c5ae.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/bn-fcef0645a47703fc.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/xgw-6c6cb7b2ed77f52e.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ge-ca1c0ba8656f9680.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/9f-e543bc691db8262e.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/global-nav-bar-ac8546fca03a5b74.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.e4334163c54cccf5.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/ql0.501e99879e15a48e.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/global-nav-bar.e9a3da281d459eec.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":"organization","label":"nullclaw","is_root":false,"href":"/nullclaw"},{"crumb_type":"repository","label":"nullclaw","is_root":false,"href":"/nullclaw/nullclaw"}],"localNavigation":[{"id":"code","icon":"code","label":"Code","href":"/nullclaw/nullclaw","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":"/nullclaw/nullclaw/issues","selectedLinks":["repo_issues","repo_labels","repo_milestones"],"count":43,"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":"/nullclaw/nullclaw/pulls","selectedLinks":["repo_pulls","checks"],"count":27,"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":"/nullclaw/nullclaw/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":"/nullclaw/nullclaw/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":"/nullclaw/nullclaw/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":"/nullclaw/nullclaw/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":"/nullclaw/nullclaw/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:nullclaw/nullclaw","current_repo_name":"nullclaw","current_repo_nwo":"nullclaw/nullclaw","current_repo_org":"nullclaw","user_id":"nullclaw"}},"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=6","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="/nullclaw" data-discover="true"><span class="">nullclaw</span></a></li><li class="prc-Breadcrumbs-ItemWrapper-k0NLn"><a class="styles-module__contextCrumb__IzGIq prc-Breadcrumbs-Item-jcraJ" data-component="Breadcrumbs.Item" href="/nullclaw/nullclaw" data-discover="true"><span class="styles-module__contextCrumbLast__tI2e3">nullclaw</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="/nullclaw/nullclaw" 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="/nullclaw/nullclaw/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">43</span><span class="prc-VisuallyHidden-VisuallyHidden-Q0qSB"> (<!-- -->43<!-- -->)</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="/nullclaw/nullclaw/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><span data-component="counter"><span aria-hidden="true" data-variant="secondary" data-component="CounterLabel" class="prc-CounterLabel-CounterLabel-X-kRU">27</span><span class="prc-VisuallyHidden-VisuallyHidden-Q0qSB"> (<!-- -->27<!-- -->)</span></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="/nullclaw/nullclaw/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="/nullclaw/nullclaw/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="/nullclaw/nullclaw/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="/nullclaw/nullclaw/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="/nullclaw/nullclaw/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_2ktl_"><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="/nullclaw/nullclaw/blob/main/docs/integration-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":"Integration Analysis: nullclaw + nullboiler + nulltickets","anchor":"integration-analysis-nullclaw--nullboiler--nulltickets","htmlText":"Integration Analysis: nullclaw + nullboiler + nulltickets"},{"level":2,"text":"Executive Summary","anchor":"executive-summary","htmlText":"Executive Summary"},{"level":2,"text":"Architecture Overview","anchor":"architecture-overview","htmlText":"Architecture Overview"},{"level":3,"text":"Project Roles","anchor":"project-roles","htmlText":"Project Roles"},{"level":2,"text":"Current Capabilities","anchor":"current-capabilities","htmlText":"Current Capabilities"},{"level":3,"text":"✅ What Already Works","anchor":"-what-already-works","htmlText":"✅ What Already Works"},{"level":2,"text":"Integration Gaps","anchor":"integration-gaps","htmlText":"Integration Gaps"},{"level":3,"text":"Gap 1: External Message Send API (HIGH PRIORITY)","anchor":"gap-1-external-message-send-api-high-priority","htmlText":"Gap 1: External Message Send API (HIGH PRIORITY)"},{"level":3,"text":"Gap 2: Callback Receiver for nullboiler (HIGH PRIORITY)","anchor":"gap-2-callback-receiver-for-nullboiler-high-priority","htmlText":"Gap 2: Callback Receiver for nullboiler (HIGH PRIORITY)"},{"level":3,"text":"Gap 3: Worker Endpoint for nullboiler Dispatch (HIGH PRIORITY)","anchor":"gap-3-worker-endpoint-for-nullboiler-dispatch-high-priority","htmlText":"Gap 3: Worker Endpoint for nullboiler Dispatch (HIGH PRIORITY)"},{"level":3,"text":"Gap 4: Self-Registration with nullboiler (MEDIUM PRIORITY)","anchor":"gap-4-self-registration-with-nullboiler-medium-priority","htmlText":"Gap 4: Self-Registration with nullboiler (MEDIUM PRIORITY)"},{"level":3,"text":"Gap 5: Dedicated Workflow Tool (MEDIUM PRIORITY)","anchor":"gap-5-dedicated-workflow-tool-medium-priority","htmlText":"Gap 5: Dedicated Workflow Tool (MEDIUM PRIORITY)"},{"level":3,"text":"Gap 6: Topic-Aware Callback Routing (MEDIUM PRIORITY)","anchor":"gap-6-topic-aware-callback-routing-medium-priority","htmlText":"Gap 6: Topic-Aware Callback Routing (MEDIUM PRIORITY)"},{"level":3,"text":"Gap 7: nulltickets Push Notifications (LOW PRIORITY)","anchor":"gap-7-nulltickets-push-notifications-low-priority","htmlText":"Gap 7: nulltickets Push Notifications (LOW PRIORITY)"},{"level":2,"text":"Implementation Roadmap","anchor":"implementation-roadmap","htmlText":"Implementation Roadmap"},{"level":3,"text":"Phase 1: Critical Path (Gaps 1-3)","anchor":"phase-1-critical-path-gaps-1-3","htmlText":"Phase 1: Critical Path (Gaps 1-3)"},{"level":3,"text":"Phase 2: Feedback Loop (Gaps 2+6)","anchor":"phase-2-feedback-loop-gaps-26","htmlText":"Phase 2: Feedback Loop (Gaps 2+6)"},{"level":3,"text":"Phase 3: Automation (Gap 4)","anchor":"phase-3-automation-gap-4","htmlText":"Phase 3: Automation (Gap 4)"},{"level":3,"text":"Phase 4: Usability (Gap 5)","anchor":"phase-4-usability-gap-5","htmlText":"Phase 4: Usability (Gap 5)"},{"level":3,"text":"Phase 5: Enhancement (Gap 7)","anchor":"phase-5-enhancement-gap-7","htmlText":"Phase 5: Enhancement (Gap 7)"},{"level":2,"text":"Technical Details","anchor":"technical-details","htmlText":"Technical Details"},{"level":3,"text":"nullclaw Gateway API Design","anchor":"nullclaw-gateway-api-design","htmlText":"nullclaw Gateway API Design"},{"level":3,"text":"nullboiler Integration Points","anchor":"nullboiler-integration-points","htmlText":"nullboiler Integration Points"},{"level":3,"text":"Data Flow Example","anchor":"data-flow-example","htmlText":"Data Flow Example"},{"level":2,"text":"Configuration Example","anchor":"configuration-example","htmlText":"Configuration Example"},{"level":2,"text":"Files Modified","anchor":"files-modified","htmlText":"Files Modified"},{"level":2,"text":"References","anchor":"references","htmlText":"References"},{"level":3,"text":"nullclaw","anchor":"nullclaw","htmlText":"nullclaw"},{"level":3,"text":"nullboiler","anchor":"nullboiler","htmlText":"nullboiler"},{"level":3,"text":"nulltickets","anchor":"nulltickets","htmlText":"nulltickets"},{"level":2,"text":"Version History","anchor":"version-history","htmlText":"Version History"}]},"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\"\u003eIntegration Analysis: nullclaw + nullboiler + nulltickets\u003c/h1\u003e\u003ca id=\"user-content-integration-analysis-nullclaw--nullboiler--nulltickets\" class=\"anchor\" aria-label=\"Permalink: Integration Analysis: nullclaw + nullboiler + nulltickets\" href=\"#integration-analysis-nullclaw--nullboiler--nulltickets\"\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=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eExecutive Summary\u003c/h2\u003e\u003ca id=\"user-content-executive-summary\" class=\"anchor\" aria-label=\"Permalink: Executive Summary\" href=\"#executive-summary\"\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\"\u003eThis document analyzes the integration gaps between three nullclaw ecosystem projects to enable end-to-end multi-agent workflows with Telegram topic routing.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eTarget Scenario:\u003c/strong\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003eUser sends message in Telegram General topic → Orchestrator agent decides to delegate coding task → Coder agent executes → Result appears in the Coder topic in Telegram\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eArchitecture Overview\u003c/h2\u003e\u003ca id=\"user-content-architecture-overview\" class=\"anchor\" aria-label=\"Permalink: Architecture Overview\" href=\"#architecture-overview\"\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=\"┌─────────────────┐     ┌──────────────────┐     ┌─────────────────┐\n│   nulltickets   │────▶│   nullboiler     │────▶│    nullclaw     │\n│  (Task Tracker) │     │ (DAG Orchestrator)│     │  (AI Runtime)   │\n└─────────────────┘     └──────────────────┘     └─────────────────┘\n         │                       │                       │\n         ▼                       ▼                       ▼\n   Pipeline FSM             Workflow DAG           Telegram Topics\n   Lease-based              Step dispatch          Agent routing\n   Role routing             Worker selection       Tool execution\"\u003e\u003cpre class=\"notranslate\"\u003e\u003ccode\u003e┌─────────────────┐     ┌──────────────────┐     ┌─────────────────┐\n│   nulltickets   │────▶│   nullboiler     │────▶│    nullclaw     │\n│  (Task Tracker) │     │ (DAG Orchestrator)│     │  (AI Runtime)   │\n└─────────────────┘     └──────────────────┘     └─────────────────┘\n         │                       │                       │\n         ▼                       ▼                       ▼\n   Pipeline FSM             Workflow DAG           Telegram Topics\n   Lease-based              Step dispatch          Agent routing\n   Role routing             Worker selection       Tool execution\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eProject Roles\u003c/h3\u003e\u003ca id=\"user-content-project-roles\" class=\"anchor\" aria-label=\"Permalink: Project Roles\" href=\"#project-roles\"\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\u003eComponent\u003c/th\u003e\n\u003cth\u003eResponsibility\u003c/th\u003e\n\u003cth\u003eKey Files\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cstrong\u003enulltickets\u003c/strong\u003e\u003c/td\u003e\n\u003ctd\u003eDurable task state, FSM transitions, lease coordination\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003esrc/api.zig\u003c/code\u003e, \u003ccode\u003esrc/store.zig\u003c/code\u003e, \u003ccode\u003esrc/domain.zig\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cstrong\u003enullboiler\u003c/strong\u003e\u003c/td\u003e\n\u003ctd\u003eDAG scheduling, worker dispatch, step orchestration\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003esrc/engine.zig\u003c/code\u003e, \u003ccode\u003esrc/dispatch.zig\u003c/code\u003e, \u003ccode\u003esrc/callbacks.zig\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cstrong\u003enullclaw\u003c/strong\u003e\u003c/td\u003e\n\u003ctd\u003eAI agent runtime, tool execution, Telegram integration\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003esrc/agent/root.zig\u003c/code\u003e, \u003ccode\u003esrc/gateway.zig\u003c/code\u003e, \u003ccode\u003esrc/session.zig\u003c/code\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\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCurrent Capabilities\u003c/h2\u003e\u003ca id=\"user-content-current-capabilities\" class=\"anchor\" aria-label=\"Permalink: Current Capabilities\" href=\"#current-capabilities\"\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=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e✅ What Already Works\u003c/h3\u003e\u003ca id=\"user-content--what-already-works\" class=\"anchor\" aria-label=\"Permalink: ✅ What Already Works\" href=\"#-what-already-works\"\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\u003col dir=\"auto\"\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eTelegram Topic Delivery\u003c/strong\u003e (\u003ccode\u003enullclaw/src/channels/telegram.zig:146-156\u003c/code\u003e)\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eSupports \u003ccode\u003echatid#topic:threadid\u003c/code\u003e format for forum topics\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eMessageTool\u003c/code\u003e can send to any channel/topic combination\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eAgent Routing per Topic\u003c/strong\u003e (\u003ccode\u003enullclaw/src/agent_bindings_config.zig\u003c/code\u003e)\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e7-tier binding system: peer → parent_peer → guild_roles → guild → team → account → default\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e/bind\u003c/code\u003e command for runtime topic-to-agent binding\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003enullboiler Callback System\u003c/strong\u003e (\u003ccode\u003enullboiler/src/callbacks.zig:21-114\u003c/code\u003e)\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eWebhook callbacks on events: \u003ccode\u003estep.completed\u003c/code\u003e, \u003ccode\u003estep.failed\u003c/code\u003e, \u003ccode\u003erun.completed\u003c/code\u003e, \u003ccode\u003erun.failed\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eSupports custom headers and HMAC signing\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003enullboiler Worker Dispatch\u003c/strong\u003e (\u003ccode\u003enullboiler/src/dispatch.zig:89-199\u003c/code\u003e)\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e5 protocols: webhook, api_chat, openai_chat, mqtt, redis_stream\u003c/li\u003e\n\u003cli\u003eTag-based worker selection with least-loaded balancing\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003enullclaw Tool System\u003c/strong\u003e (\u003ccode\u003enullclaw/src/tools/root.zig\u003c/code\u003e)\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003eMessageTool\u003c/code\u003e — send to any channel/topic internally\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eDelegateTool\u003c/code\u003e — synchronous sub-agent delegation\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eHttpRequestTool\u003c/code\u003e — arbitrary HTTP calls\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eAgent Profile System\u003c/strong\u003e (\u003ccode\u003enullclaw/src/config.zig\u003c/code\u003e)\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eNamed agents with different providers, models, system prompts\u003c/li\u003e\n\u003cli\u003eSession-scoped agent instances\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eIntegration Gaps\u003c/h2\u003e\u003ca id=\"user-content-integration-gaps\" class=\"anchor\" aria-label=\"Permalink: Integration Gaps\" href=\"#integration-gaps\"\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=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eGap 1: External Message Send API (HIGH PRIORITY)\u003c/h3\u003e\u003ca id=\"user-content-gap-1-external-message-send-api-high-priority\" class=\"anchor\" aria-label=\"Permalink: Gap 1: External Message Send API (HIGH PRIORITY)\" href=\"#gap-1-external-message-send-api-high-priority\"\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\u003cstrong\u003eProblem:\u003c/strong\u003e nullclaw's gateway is inbound-only. No endpoint exists for external services (like nullboiler) to trigger outbound messages to specific Telegram topics.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eCurrent State:\u003c/strong\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eGateway endpoints: \u003ccode\u003e/health\u003c/code\u003e, \u003ccode\u003e/ready\u003c/code\u003e, \u003ccode\u003e/pair\u003c/code\u003e, \u003ccode\u003e/webhook\u003c/code\u003e, \u003ccode\u003e/telegram\u003c/code\u003e, \u003ccode\u003e/whatsapp\u003c/code\u003e, \u003ccode\u003e/a2a\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eNo \u003ccode\u003e/api/send\u003c/code\u003e or similar endpoint\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eRequired:\u003c/strong\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eNew \u003ccode\u003ePOST /api/send\u003c/code\u003e endpoint in \u003ccode\u003enullclaw/src/gateway.zig\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAccept JSON: \u003ccode\u003e{channel: \"telegram\", chat_id: \"-100123#topic:456\", content: \"...\"}\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eHook into \u003ccode\u003ebus.Bus.publishOutbound()\u003c/code\u003e for delivery\u003c/li\u003e\n\u003cli\u003eAuthentication via existing token/pairing system\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eImplementation Notes:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-zig notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"// Potential endpoint structure in gateway.zig\nPOST /api/send\nBody: {\n  \u0026quot;channel\u0026quot;: \u0026quot;telegram\u0026quot;,\n  \u0026quot;chat_id\u0026quot;: \u0026quot;-1001234567890#topic:42\u0026quot;,\n  \u0026quot;content\u0026quot;: \u0026quot;Coder agent completed the task...\u0026quot;,\n  \u0026quot;reply_to_message_id\u0026quot;: null\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e// Potential endpoint structure in gateway.zig\u003c/span\u003e\n\u003cspan class=\"pl-v\"\u003ePOST\u003c/span\u003e \u003cspan class=\"pl-k\"\u003e/\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eapi\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e/\u003c/span\u003e\u003cspan class=\"pl-v\"\u003esend\u003c/span\u003e\n\u003cspan class=\"pl-en\"\u003eBody\u003c/span\u003e: {\n  \u003cspan class=\"pl-s\"\u003e\"channel\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"telegram\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"chat_id\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"-1001234567890#topic:42\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"content\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"Coder agent completed the task...\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"reply_to_message_id\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003enull\u003c/span\u003e\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eGap 2: Callback Receiver for nullboiler (HIGH PRIORITY)\u003c/h3\u003e\u003ca id=\"user-content-gap-2-callback-receiver-for-nullboiler-high-priority\" class=\"anchor\" aria-label=\"Permalink: Gap 2: Callback Receiver for nullboiler (HIGH PRIORITY)\" href=\"#gap-2-callback-receiver-for-nullboiler-high-priority\"\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\u003cstrong\u003eProblem:\u003c/strong\u003e nullboiler can fire callbacks when steps complete, but nullclaw has no endpoint to receive them.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eCurrent State:\u003c/strong\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003enullboiler fires callbacks: \u003ccode\u003efireCallbacks()\u003c/code\u003e in \u003ccode\u003enullboiler/src/callbacks.zig:21-114\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eCallback format: \u003ccode\u003e{event, run_id, step_id, output, status}\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003enullclaw has no \u003ccode\u003e/api/callback\u003c/code\u003e endpoint\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eRequired:\u003c/strong\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eNew \u003ccode\u003ePOST /api/callback\u003c/code\u003e endpoint in \u003ccode\u003enullclaw/src/gateway.zig\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eParse nullboiler callback format\u003c/li\u003e\n\u003cli\u003eRoute results to appropriate Telegram topic via outbound bus\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eImplementation Notes:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-zig notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"// Callback format from nullboiler/src/callbacks.zig\n{\n  \u0026quot;event\u0026quot;: \u0026quot;step.completed\u0026quot;,\n  \u0026quot;run_id\u0026quot;: \u0026quot;run-uuid\u0026quot;,\n  \u0026quot;step_id\u0026quot;: \u0026quot;code\u0026quot;,\n  \u0026quot;output\u0026quot;: \u0026quot;The generated bash script...\u0026quot;,\n  \u0026quot;status\u0026quot;: \u0026quot;ok\u0026quot;\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e// Callback format from nullboiler/src/callbacks.zig\u003c/span\u003e\n{\n  \u003cspan class=\"pl-s\"\u003e\"event\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"step.completed\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"run_id\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"run-uuid\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"step_id\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"code\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"output\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"The generated bash script...\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"status\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"ok\"\u003c/span\u003e\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eGap 3: Worker Endpoint for nullboiler Dispatch (HIGH PRIORITY)\u003c/h3\u003e\u003ca id=\"user-content-gap-3-worker-endpoint-for-nullboiler-dispatch-high-priority\" class=\"anchor\" aria-label=\"Permalink: Gap 3: Worker Endpoint for nullboiler Dispatch (HIGH PRIORITY)\" href=\"#gap-3-worker-endpoint-for-nullboiler-dispatch-high-priority\"\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\u003cstrong\u003eProblem:\u003c/strong\u003e nullboiler dispatches steps to workers via HTTP POST, but nullclaw has no endpoint that accepts nullboiler's step format.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eCurrent State:\u003c/strong\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003enullboiler dispatches: \u003ccode\u003edispatchStep()\u003c/code\u003e in \u003ccode\u003enullboiler/src/dispatch.zig:89-199\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eDispatch payload: \u003ccode\u003e{prompt, context, step_id, run_id, correlation_id}\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003enullclaw's \u003ccode\u003e/webhook\u003c/code\u003e is designed for Telegram, not generic worker tasks\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eRequired:\u003c/strong\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eNew \u003ccode\u003ePOST /api/worker\u003c/code\u003e endpoint in \u003ccode\u003enullclaw/src/gateway.zig\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAccept nullboiler step dispatch format\u003c/li\u003e\n\u003cli\u003eRoute to appropriate agent via \u003ccode\u003eagent_routing.resolveRoute()\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eReturn response in format: \u003ccode\u003e{status:\"ok\", response:\"...\"}\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eHandle via \u003ccode\u003esession_mgr.processMessage()\u003c/code\u003e for agent execution\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eImplementation Notes:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-zig notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"// Worker dispatch payload from nullboiler\n{\n  \u0026quot;prompt\u0026quot;: \u0026quot;Generate a bash script that...\u0026quot;,\n  \u0026quot;context\u0026quot;: {\u0026quot;previous_output\u0026quot;: \u0026quot;...\u0026quot;},\n  \u0026quot;step_id\u0026quot;: \u0026quot;code\u0026quot;,\n  \u0026quot;run_id\u0026quot;: \u0026quot;run-uuid\u0026quot;,\n  \u0026quot;correlation_id\u0026quot;: \u0026quot;corr-uuid\u0026quot;\n}\n\n// Expected response format (nullboiler/src/worker_response.zig:102)\n{\n  \u0026quot;status\u0026quot;: \u0026quot;ok\u0026quot;,\n  \u0026quot;response\u0026quot;: \u0026quot;#!/bin/bash\\necho 'Hello World'\u0026quot;\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e// Worker dispatch payload from nullboiler\u003c/span\u003e\n{\n  \u003cspan class=\"pl-s\"\u003e\"prompt\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"Generate a bash script that...\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"context\"\u003c/span\u003e: {\u003cspan class=\"pl-s\"\u003e\"previous_output\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"...\"\u003c/span\u003e},\n  \u003cspan class=\"pl-s\"\u003e\"step_id\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"code\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"run_id\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"run-uuid\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"correlation_id\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"corr-uuid\"\u003c/span\u003e\n}\n\n\u003cspan class=\"pl-c\"\u003e// Expected response format (nullboiler/src/worker_response.zig:102)\u003c/span\u003e\n{\n  \u003cspan class=\"pl-s\"\u003e\"status\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"ok\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"response\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"#!/bin/bash\u003cspan class=\"pl-cce\"\u003e\\n\u003c/span\u003eecho 'Hello World'\"\u003c/span\u003e\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eGap 4: Self-Registration with nullboiler (MEDIUM PRIORITY)\u003c/h3\u003e\u003ca id=\"user-content-gap-4-self-registration-with-nullboiler-medium-priority\" class=\"anchor\" aria-label=\"Permalink: Gap 4: Self-Registration with nullboiler (MEDIUM PRIORITY)\" href=\"#gap-4-self-registration-with-nullboiler-medium-priority\"\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\u003cstrong\u003eProblem:\u003c/strong\u003e nullclaw cannot automatically register itself as a nullboiler worker on startup.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eCurrent State:\u003c/strong\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003enullboiler has \u003ccode\u003ePOST /workers\u003c/code\u003e endpoint (\u003ccode\u003enullboiler/src/api.zig:135\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003enullclaw has no startup registration logic\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eRequired:\u003c/strong\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eConfig additions: \u003ccode\u003enullboiler.url\u003c/code\u003e, \u003ccode\u003enullboiler.worker_id\u003c/code\u003e, \u003ccode\u003enullboiler.tags\u003c/code\u003e, \u003ccode\u003enullboiler.capacity\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eStartup hook in \u003ccode\u003enullclaw/src/daemon.zig\u003c/code\u003e or new \u003ccode\u003enullclaw/src/boiler_client.zig\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eHTTP POST to \u003ccode\u003e{nullboiler_url}/workers\u003c/code\u003e with registration payload\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eImplementation Notes:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-zig notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"// Registration payload\n{\n  \u0026quot;id\u0026quot;: \u0026quot;nullclaw-coder-1\u0026quot;,\n  \u0026quot;url\u0026quot;: \u0026quot;http://nullclaw:8080/api/worker\u0026quot;,\n  \u0026quot;protocol\u0026quot;: \u0026quot;webhook\u0026quot;,\n  \u0026quot;tags\u0026quot;: [\u0026quot;coder\u0026quot;, \u0026quot;bash\u0026quot;],\n  \u0026quot;max_concurrent\u0026quot;: 3\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e// Registration payload\u003c/span\u003e\n{\n  \u003cspan class=\"pl-s\"\u003e\"id\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"nullclaw-coder-1\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"url\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"http://nullclaw:8080/api/worker\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"protocol\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"webhook\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"tags\"\u003c/span\u003e: [\u003cspan class=\"pl-s\"\u003e\"coder\"\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e\"bash\"\u003c/span\u003e],\n  \u003cspan class=\"pl-s\"\u003e\"max_concurrent\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eGap 5: Dedicated Workflow Tool (MEDIUM PRIORITY)\u003c/h3\u003e\u003ca id=\"user-content-gap-5-dedicated-workflow-tool-medium-priority\" class=\"anchor\" aria-label=\"Permalink: Gap 5: Dedicated Workflow Tool (MEDIUM PRIORITY)\" href=\"#gap-5-dedicated-workflow-tool-medium-priority\"\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\u003cstrong\u003eProblem:\u003c/strong\u003e Orchestrator agent must manually construct nullboiler API calls using \u003ccode\u003ehttp_request\u003c/code\u003e tool, which is error-prone.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eCurrent State:\u003c/strong\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003enullboiler \u003ccode\u003ePOST /runs\u003c/code\u003e endpoint exists (\u003ccode\u003enullboiler/src/api.zig:70\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003enullclaw \u003ccode\u003ehttp_request\u003c/code\u003e tool can make arbitrary calls\u003c/li\u003e\n\u003cli\u003eNo high-level workflow abstraction\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eRequired:\u003c/strong\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eNew \u003ccode\u003ecreate_workflow\u003c/code\u003e tool in \u003ccode\u003enullclaw/src/tools/workflow.zig\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eWrap nullboiler \u003ccode\u003ePOST /runs\u003c/code\u003e API\u003c/li\u003e\n\u003cli\u003eAuto-set callback URL to nullclaw's gateway\u003c/li\u003e\n\u003cli\u003eSimplified interface for agent\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eImplementation Notes:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-zig notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"// Tool interface\n{\n  \u0026quot;name\u0026quot;: \u0026quot;create_workflow\u0026quot;,\n  \u0026quot;arguments\u0026quot;: {\n    \u0026quot;workflow_name\u0026quot;: \u0026quot;code-review\u0026quot;,\n    \u0026quot;inputs\u0026quot;: {\u0026quot;task\u0026quot;: \u0026quot;Create bash script\u0026quot;},\n    \u0026quot;telegram_target\u0026quot;: \u0026quot;-100123#topic:456\u0026quot;\n  }\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e// Tool interface\u003c/span\u003e\n{\n  \u003cspan class=\"pl-s\"\u003e\"name\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"create_workflow\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"arguments\"\u003c/span\u003e: {\n    \u003cspan class=\"pl-s\"\u003e\"workflow_name\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"code-review\"\u003c/span\u003e,\n    \u003cspan class=\"pl-s\"\u003e\"inputs\"\u003c/span\u003e: {\u003cspan class=\"pl-s\"\u003e\"task\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"Create bash script\"\u003c/span\u003e},\n    \u003cspan class=\"pl-s\"\u003e\"telegram_target\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"-100123#topic:456\"\u003c/span\u003e\n  }\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eGap 6: Topic-Aware Callback Routing (MEDIUM PRIORITY)\u003c/h3\u003e\u003ca id=\"user-content-gap-6-topic-aware-callback-routing-medium-priority\" class=\"anchor\" aria-label=\"Permalink: Gap 6: Topic-Aware Callback Routing (MEDIUM PRIORITY)\" href=\"#gap-6-topic-aware-callback-routing-medium-priority\"\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\u003cstrong\u003eProblem:\u003c/strong\u003e When nullboiler sends a callback, nullclaw needs to know which Telegram topic to route the result to.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eCurrent State:\u003c/strong\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eCallbacks contain run/step metadata but no Telegram routing info\u003c/li\u003e\n\u003cli\u003eAgent bindings config has topic mappings\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eRequired:\u003c/strong\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eStore \u003ccode\u003etelegram_target\u003c/code\u003e (chat_id#topic) in run metadata when creating workflow\u003c/li\u003e\n\u003cli\u003eInclude in callback payload or correlate via run_id\u003c/li\u003e\n\u003cli\u003eCallback receiver looks up target and routes via outbound bus\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eImplementation Notes:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-zig notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"// Store in run creation\nPOST /runs\n{\n  \u0026quot;workflow\u0026quot;: {...},\n  \u0026quot;inputs\u0026quot;: {...},\n  \u0026quot;metadata\u0026quot;: {\n    \u0026quot;telegram_target\u0026quot;: \u0026quot;-100123#topic:456\u0026quot;,\n    \u0026quot;origin_chat_id\u0026quot;: \u0026quot;-100123\u0026quot;,\n    \u0026quot;origin_topic_id\u0026quot;: \u0026quot;42\u0026quot;\n  }\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e// Store in run creation\u003c/span\u003e\n\u003cspan class=\"pl-v\"\u003ePOST\u003c/span\u003e \u003cspan class=\"pl-k\"\u003e/\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eruns\u003c/span\u003e\n{\n  \u003cspan class=\"pl-s\"\u003e\"workflow\"\u003c/span\u003e: {\u003cspan class=\"pl-k\"\u003e...\u003c/span\u003e},\n  \u003cspan class=\"pl-s\"\u003e\"inputs\"\u003c/span\u003e: {\u003cspan class=\"pl-k\"\u003e...\u003c/span\u003e},\n  \u003cspan class=\"pl-s\"\u003e\"metadata\"\u003c/span\u003e: {\n    \u003cspan class=\"pl-s\"\u003e\"telegram_target\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"-100123#topic:456\"\u003c/span\u003e,\n    \u003cspan class=\"pl-s\"\u003e\"origin_chat_id\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"-100123\"\u003c/span\u003e,\n    \u003cspan class=\"pl-s\"\u003e\"origin_topic_id\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"42\"\u003c/span\u003e\n  }\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eGap 7: nulltickets Push Notifications (LOW PRIORITY)\u003c/h3\u003e\u003ca id=\"user-content-gap-7-nulltickets-push-notifications-low-priority\" class=\"anchor\" aria-label=\"Permalink: Gap 7: nulltickets Push Notifications (LOW PRIORITY)\" href=\"#gap-7-nulltickets-push-notifications-low-priority\"\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\u003cstrong\u003eProblem:\u003c/strong\u003e nulltickets is pull-based (lease/claim). No push/webhook mechanism for real-time notifications.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eCurrent State:\u003c/strong\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003enulltickets API: claim tasks via \u003ccode\u003ePOST /leases/claim\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eNo webhook subscription endpoint\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eImpact:\u003c/strong\u003e Low — nullboiler already bridges via \u003ccode\u003etracker_client.zig\u003c/code\u003e polling\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eRequired (if needed):\u003c/strong\u003e\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eNew webhook subscription API in \u003ccode\u003enulltickets/src/api.zig\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eFire webhooks on stage transitions\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eImplementation Roadmap\u003c/h2\u003e\u003ca id=\"user-content-implementation-roadmap\" class=\"anchor\" aria-label=\"Permalink: Implementation Roadmap\" href=\"#implementation-roadmap\"\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=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ePhase 1: Critical Path (Gaps 1-3)\u003c/h3\u003e\u003ca id=\"user-content-phase-1-critical-path-gaps-1-3\" class=\"anchor\" aria-label=\"Permalink: Phase 1: Critical Path (Gaps 1-3)\" href=\"#phase-1-critical-path-gaps-1-3\"\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\"\u003eWithout these, nullboiler cannot communicate with nullclaw at all.\u003c/p\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eWorker Endpoint\u003c/strong\u003e (\u003ccode\u003ePOST /api/worker\u003c/code\u003e)\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eAccept nullboiler step dispatch\u003c/li\u003e\n\u003cli\u003eRoute to agent via session manager\u003c/li\u003e\n\u003cli\u003eReturn synchronous response\u003c/li\u003e\n\u003cli\u003eFile: \u003ccode\u003enullclaw/src/gateway.zig\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eExternal Send API\u003c/strong\u003e (\u003ccode\u003ePOST /api/send\u003c/code\u003e)\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eAccept authenticated requests to send messages\u003c/li\u003e\n\u003cli\u003eHook into outbound bus\u003c/li\u003e\n\u003cli\u003eSupport topic format \u003ccode\u003echatid#topic:threadid\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eFile: \u003ccode\u003enullclaw/src/gateway.zig\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eCallback Receiver\u003c/strong\u003e (\u003ccode\u003ePOST /api/callback\u003c/code\u003e)\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eAccept nullboiler callbacks\u003c/li\u003e\n\u003cli\u003eParse event types\u003c/li\u003e\n\u003cli\u003eRoute to appropriate handler\u003c/li\u003e\n\u003cli\u003eFile: \u003ccode\u003enullclaw/src/gateway.zig\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ePhase 2: Feedback Loop (Gaps 2+6)\u003c/h3\u003e\u003ca id=\"user-content-phase-2-feedback-loop-gaps-26\" class=\"anchor\" aria-label=\"Permalink: Phase 2: Feedback Loop (Gaps 2+6)\" href=\"#phase-2-feedback-loop-gaps-26\"\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\"\u003eClose the loop so workflow results reach the right Telegram topic.\u003c/p\u003e\n\u003col start=\"4\" dir=\"auto\"\u003e\n\u003cli\u003e\u003cstrong\u003eTopic-Aware Routing\u003c/strong\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eStore telegram_target in run metadata\u003c/li\u003e\n\u003cli\u003eCallback receiver extracts and routes\u003c/li\u003e\n\u003cli\u003eIntegration with agent bindings\u003c/li\u003e\n\u003cli\u003eFiles: \u003ccode\u003enullclaw/src/gateway.zig\u003c/code\u003e, \u003ccode\u003enullboiler\u003c/code\u003e run creation\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ePhase 3: Automation (Gap 4)\u003c/h3\u003e\u003ca id=\"user-content-phase-3-automation-gap-4\" class=\"anchor\" aria-label=\"Permalink: Phase 3: Automation (Gap 4)\" href=\"#phase-3-automation-gap-4\"\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\u003col start=\"5\" dir=\"auto\"\u003e\n\u003cli\u003e\u003cstrong\u003eSelf-Registration\u003c/strong\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eConfig schema additions\u003c/li\u003e\n\u003cli\u003eStartup registration logic\u003c/li\u003e\n\u003cli\u003eHealth check pings\u003c/li\u003e\n\u003cli\u003eFile: \u003ccode\u003enullclaw/src/daemon.zig\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ePhase 4: Usability (Gap 5)\u003c/h3\u003e\u003ca id=\"user-content-phase-4-usability-gap-5\" class=\"anchor\" aria-label=\"Permalink: Phase 4: Usability (Gap 5)\" href=\"#phase-4-usability-gap-5\"\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\u003col start=\"6\" dir=\"auto\"\u003e\n\u003cli\u003e\u003cstrong\u003eWorkflow Tool\u003c/strong\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eHigh-level tool for orchestrator agents\u003c/li\u003e\n\u003cli\u003eAuto-configure callbacks\u003c/li\u003e\n\u003cli\u003eSchema validation\u003c/li\u003e\n\u003cli\u003eFile: \u003ccode\u003enullclaw/src/tools/workflow.zig\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ePhase 5: Enhancement (Gap 7)\u003c/h3\u003e\u003ca id=\"user-content-phase-5-enhancement-gap-7\" class=\"anchor\" aria-label=\"Permalink: Phase 5: Enhancement (Gap 7)\" href=\"#phase-5-enhancement-gap-7\"\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\u003col start=\"7\" dir=\"auto\"\u003e\n\u003cli\u003e\u003cstrong\u003enulltickets Push\u003c/strong\u003e (optional)\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eWebhook subscription API\u003c/li\u003e\n\u003cli\u003eStage transition events\u003c/li\u003e\n\u003cli\u003eFile: \u003ccode\u003enulltickets/src/api.zig\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTechnical Details\u003c/h2\u003e\u003ca id=\"user-content-technical-details\" class=\"anchor\" aria-label=\"Permalink: Technical Details\" href=\"#technical-details\"\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=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003enullclaw Gateway API Design\u003c/h3\u003e\u003ca id=\"user-content-nullclaw-gateway-api-design\" class=\"anchor\" aria-label=\"Permalink: nullclaw Gateway API Design\" href=\"#nullclaw-gateway-api-design\"\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-zig notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"// New endpoints to add in nullclaw/src/gateway.zig\n\n// 1. Worker endpoint for nullboiler dispatch\nPOST /api/worker\nContent-Type: application/json\nAuthorization: Bearer \u0026lt;token\u0026gt;\n\nRequest:\n{\n  \u0026quot;prompt\u0026quot;: \u0026quot;Generate a bash script that...\u0026quot;,\n  \u0026quot;context\u0026quot;: {\u0026quot;previous_output\u0026quot;: \u0026quot;...\u0026quot;},\n  \u0026quot;step_id\u0026quot;: \u0026quot;code\u0026quot;,\n  \u0026quot;run_id\u0026quot;: \u0026quot;run-uuid\u0026quot;,\n  \u0026quot;correlation_id\u0026quot;: \u0026quot;corr-uuid\u0026quot;\n}\n\nResponse:\n{\n  \u0026quot;status\u0026quot;: \u0026quot;ok\u0026quot;,\n  \u0026quot;response\u0026quot;: \u0026quot;#!/bin/bash\\necho 'Hello World'\u0026quot;,\n  \u0026quot;correlation_id\u0026quot;: \u0026quot;corr-uuid\u0026quot;\n}\n\n// 2. External message send\nPOST /api/send\nContent-Type: application/json\nAuthorization: Bearer \u0026lt;token\u0026gt;\n\nRequest:\n{\n  \u0026quot;channel\u0026quot;: \u0026quot;telegram\u0026quot;,\n  \u0026quot;chat_id\u0026quot;: \u0026quot;-1001234567890#topic:42\u0026quot;,\n  \u0026quot;content\u0026quot;: \u0026quot;Task completed successfully!\u0026quot;,\n  \u0026quot;reply_to_message_id\u0026quot;: null\n}\n\nResponse:\n{\n  \u0026quot;status\u0026quot;: \u0026quot;ok\u0026quot;,\n  \u0026quot;message_id\u0026quot;: \u0026quot;12345\u0026quot;\n}\n\n// 3. Callback receiver\nPOST /api/callback\nContent-Type: application/json\nAuthorization: Bearer \u0026lt;token\u0026gt;\n\nRequest:\n{\n  \u0026quot;event\u0026quot;: \u0026quot;step.completed\u0026quot;,\n  \u0026quot;run_id\u0026quot;: \u0026quot;run-uuid\u0026quot;,\n  \u0026quot;step_id\u0026quot;: \u0026quot;code\u0026quot;,\n  \u0026quot;output\u0026quot;: \u0026quot;Generated script content...\u0026quot;,\n  \u0026quot;metadata\u0026quot;: {\n    \u0026quot;telegram_target\u0026quot;: \u0026quot;-100123#topic:42\u0026quot;\n  }\n}\n\nResponse:\n{\n  \u0026quot;status\u0026quot;: \u0026quot;received\u0026quot;\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e// New endpoints to add in nullclaw/src/gateway.zig\u003c/span\u003e\n\n\u003cspan class=\"pl-c\"\u003e// 1. Worker endpoint for nullboiler dispatch\u003c/span\u003e\n\u003cspan class=\"pl-v\"\u003ePOST\u003c/span\u003e \u003cspan class=\"pl-k\"\u003e/\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eapi\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e/\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eworker\u003c/span\u003e\n\u003cspan class=\"pl-en\"\u003eContent\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eType\u003c/span\u003e: \u003cspan class=\"pl-v\"\u003eapplication\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e/\u003c/span\u003e\u003cspan class=\"pl-k\"\u003ejson\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003eAuthorization\u003c/span\u003e: \u003cspan class=\"pl-en\"\u003eBearer\u003c/span\u003e \u003cspan class=\"pl-k\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-v\"\u003etoken\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e\u0026gt;\u003c/span\u003e\n\n\u003cspan class=\"pl-smi\"\u003eRequest\u003c/span\u003e:\n{\n  \u003cspan class=\"pl-s\"\u003e\"prompt\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"Generate a bash script that...\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"context\"\u003c/span\u003e: {\u003cspan class=\"pl-s\"\u003e\"previous_output\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"...\"\u003c/span\u003e},\n  \u003cspan class=\"pl-s\"\u003e\"step_id\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"code\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"run_id\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"run-uuid\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"correlation_id\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"corr-uuid\"\u003c/span\u003e\n}\n\n\u003cspan class=\"pl-smi\"\u003eResponse\u003c/span\u003e:\n{\n  \u003cspan class=\"pl-s\"\u003e\"status\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"ok\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"response\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"#!/bin/bash\u003cspan class=\"pl-cce\"\u003e\\n\u003c/span\u003eecho 'Hello World'\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"correlation_id\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"corr-uuid\"\u003c/span\u003e\n}\n\n\u003cspan class=\"pl-c\"\u003e// 2. External message send\u003c/span\u003e\n\u003cspan class=\"pl-v\"\u003ePOST\u003c/span\u003e \u003cspan class=\"pl-k\"\u003e/\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eapi\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e/\u003c/span\u003e\u003cspan class=\"pl-v\"\u003esend\u003c/span\u003e\n\u003cspan class=\"pl-en\"\u003eContent\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eType\u003c/span\u003e: \u003cspan class=\"pl-v\"\u003eapplication\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e/\u003c/span\u003e\u003cspan class=\"pl-k\"\u003ejson\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003eAuthorization\u003c/span\u003e: \u003cspan class=\"pl-en\"\u003eBearer\u003c/span\u003e \u003cspan class=\"pl-k\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-v\"\u003etoken\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e\u0026gt;\u003c/span\u003e\n\n\u003cspan class=\"pl-smi\"\u003eRequest\u003c/span\u003e:\n{\n  \u003cspan class=\"pl-s\"\u003e\"channel\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"telegram\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"chat_id\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"-1001234567890#topic:42\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"content\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"Task completed successfully!\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"reply_to_message_id\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003enull\u003c/span\u003e\n}\n\n\u003cspan class=\"pl-smi\"\u003eResponse\u003c/span\u003e:\n{\n  \u003cspan class=\"pl-s\"\u003e\"status\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"ok\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"message_id\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"12345\"\u003c/span\u003e\n}\n\n\u003cspan class=\"pl-c\"\u003e// 3. Callback receiver\u003c/span\u003e\n\u003cspan class=\"pl-v\"\u003ePOST\u003c/span\u003e \u003cspan class=\"pl-k\"\u003e/\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eapi\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e/\u003c/span\u003e\u003cspan class=\"pl-v\"\u003ecallback\u003c/span\u003e\n\u003cspan class=\"pl-en\"\u003eContent\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eType\u003c/span\u003e: \u003cspan class=\"pl-v\"\u003eapplication\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e/\u003c/span\u003e\u003cspan class=\"pl-k\"\u003ejson\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003eAuthorization\u003c/span\u003e: \u003cspan class=\"pl-en\"\u003eBearer\u003c/span\u003e \u003cspan class=\"pl-k\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-v\"\u003etoken\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e\u0026gt;\u003c/span\u003e\n\n\u003cspan class=\"pl-smi\"\u003eRequest\u003c/span\u003e:\n{\n  \u003cspan class=\"pl-s\"\u003e\"event\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"step.completed\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"run_id\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"run-uuid\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"step_id\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"code\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"output\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"Generated script content...\"\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\"metadata\"\u003c/span\u003e: {\n    \u003cspan class=\"pl-s\"\u003e\"telegram_target\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"-100123#topic:42\"\u003c/span\u003e\n  }\n}\n\n\u003cspan class=\"pl-smi\"\u003eResponse\u003c/span\u003e:\n{\n  \u003cspan class=\"pl-s\"\u003e\"status\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\"received\"\u003c/span\u003e\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003enullboiler Integration Points\u003c/h3\u003e\u003ca id=\"user-content-nullboiler-integration-points\" class=\"anchor\" aria-label=\"Permalink: nullboiler Integration Points\" href=\"#nullboiler-integration-points\"\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-zig notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"// nullboiler/src/callbacks.zig - existing callback firing\n// This already works, just needs a target endpoint\n\npub fn fireCallbacks(\n    allocator: std.mem.Allocator,\n    callbacks: []const Callback,\n    event: Event,\n    run_id: []const u8,\n    step_id: ?[]const u8,\n    output: ?[]const u8,\n) !void {\n    // Callback POST to nullclaw /api/callback\n    // Include telegram_target from run metadata\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e// nullboiler/src/callbacks.zig - existing callback firing\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e// This already works, just needs a target endpoint\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003epub\u003c/span\u003e \u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003efireCallbacks\u003c/span\u003e(\n    \u003cspan class=\"pl-v\"\u003eallocator\u003c/span\u003e: \u003cspan class=\"pl-k\"\u003estd.mem.Allocator\u003c/span\u003e,\n    \u003cspan class=\"pl-v\"\u003ecallbacks\u003c/span\u003e: []\u003cspan class=\"pl-k\"\u003econst\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eCallback\u003c/span\u003e,\n    \u003cspan class=\"pl-v\"\u003eevent\u003c/span\u003e: \u003cspan class=\"pl-k\"\u003eEvent\u003c/span\u003e,\n    \u003cspan class=\"pl-v\"\u003erun_id\u003c/span\u003e: []\u003cspan class=\"pl-k\"\u003econst\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eu8\u003c/span\u003e,\n    \u003cspan class=\"pl-v\"\u003estep_id\u003c/span\u003e: \u003cspan class=\"pl-k\"\u003e?\u003c/span\u003e[]\u003cspan class=\"pl-k\"\u003econst\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eu8\u003c/span\u003e,\n    \u003cspan class=\"pl-v\"\u003eoutput\u003c/span\u003e: \u003cspan class=\"pl-k\"\u003e?\u003c/span\u003e[]\u003cspan class=\"pl-k\"\u003econst\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eu8\u003c/span\u003e,\n) \u003cspan class=\"pl-k\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-k\"\u003evoid\u003c/span\u003e {\n    \u003cspan class=\"pl-c\"\u003e// Callback POST to nullclaw /api/callback\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// Include telegram_target from run metadata\u003c/span\u003e\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eData Flow Example\u003c/h3\u003e\u003ca id=\"user-content-data-flow-example\" class=\"anchor\" aria-label=\"Permalink: Data Flow Example\" href=\"#data-flow-example\"\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=\"User in General topic:\n  \u0026quot;Write a bash script that backs up my home directory\u0026quot;\n\n1. nullclaw receives via Telegram webhook\n2. Agent \u0026quot;orchestrator\u0026quot; processes message\n3. Agent calls create_workflow tool\n   → POST to nullboiler /runs\n   → Metadata includes: telegram_target=\u0026quot;general#topic:1\u0026quot;\n\nnullboiler:\n4. Creates workflow run\n5. Dispatches \u0026quot;code\u0026quot; step to \u0026quot;coder\u0026quot; worker (nullclaw instance)\n   → POST to nullclaw /api/worker\n\nnullclaw (coder):\n6. Receives step dispatch\n7. Agent \u0026quot;coder\u0026quot; generates script\n8. Returns response to nullboiler\n\nnullboiler:\n9. Step completes\n10. Fires callback\n    → POST to nullclaw /api/callback\n    → Includes output + telegram_target\n\nnullclaw:\n11. Callback receiver parses event\n12. Routes output to telegram_target\n    → POST internally to /api/send\n    → Delivers to General topic\n\nUser sees:\n  [In General topic] \u0026quot;Here's the backup script: ...\u0026quot;\"\u003e\u003cpre class=\"notranslate\"\u003e\u003ccode\u003eUser in General topic:\n  \"Write a bash script that backs up my home directory\"\n\n1. nullclaw receives via Telegram webhook\n2. Agent \"orchestrator\" processes message\n3. Agent calls create_workflow tool\n   → POST to nullboiler /runs\n   → Metadata includes: telegram_target=\"general#topic:1\"\n\nnullboiler:\n4. Creates workflow run\n5. Dispatches \"code\" step to \"coder\" worker (nullclaw instance)\n   → POST to nullclaw /api/worker\n\nnullclaw (coder):\n6. Receives step dispatch\n7. Agent \"coder\" generates script\n8. Returns response to nullboiler\n\nnullboiler:\n9. Step completes\n10. Fires callback\n    → POST to nullclaw /api/callback\n    → Includes output + telegram_target\n\nnullclaw:\n11. Callback receiver parses event\n12. Routes output to telegram_target\n    → POST internally to /api/send\n    → Delivers to General topic\n\nUser sees:\n  [In General topic] \"Here's the backup script: ...\"\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eConfiguration Example\u003c/h2\u003e\u003ca id=\"user-content-configuration-example\" class=\"anchor\" aria-label=\"Permalink: Configuration Example\" href=\"#configuration-example\"\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-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"// nullclaw config.json additions\n{\n  \u0026quot;nullboiler\u0026quot;: {\n    \u0026quot;url\u0026quot;: \u0026quot;http://nullboiler:8080\u0026quot;,\n    \u0026quot;worker_id\u0026quot;: \u0026quot;nullclaw-main\u0026quot;,\n    \u0026quot;tags\u0026quot;: [\u0026quot;orchestrator\u0026quot;, \u0026quot;general\u0026quot;],\n    \u0026quot;max_concurrent\u0026quot;: 5,\n    \u0026quot;auto_register\u0026quot;: true\n  },\n  \u0026quot;gateway\u0026quot;: {\n    \u0026quot;enable_worker_endpoint\u0026quot;: true,\n    \u0026quot;enable_callback_endpoint\u0026quot;: true,\n    \u0026quot;enable_send_api\u0026quot;: true\n  }\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-ii\"\u003e// nullclaw config.json additions\u003c/span\u003e\n{\n  \u003cspan class=\"pl-ent\"\u003e\"nullboiler\"\u003c/span\u003e: {\n    \u003cspan class=\"pl-ent\"\u003e\"url\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003ehttp://nullboiler:8080\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e,\n    \u003cspan class=\"pl-ent\"\u003e\"worker_id\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003enullclaw-main\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e,\n    \u003cspan class=\"pl-ent\"\u003e\"tags\"\u003c/span\u003e: [\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003eorchestrator\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003egeneral\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e],\n    \u003cspan class=\"pl-ent\"\u003e\"max_concurrent\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003e5\u003c/span\u003e,\n    \u003cspan class=\"pl-ent\"\u003e\"auto_register\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003etrue\u003c/span\u003e\n  },\n  \u003cspan class=\"pl-ent\"\u003e\"gateway\"\u003c/span\u003e: {\n    \u003cspan class=\"pl-ent\"\u003e\"enable_worker_endpoint\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003etrue\u003c/span\u003e,\n    \u003cspan class=\"pl-ent\"\u003e\"enable_callback_endpoint\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003etrue\u003c/span\u003e,\n    \u003cspan class=\"pl-ent\"\u003e\"enable_send_api\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003etrue\u003c/span\u003e\n  }\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eFiles Modified\u003c/h2\u003e\u003ca id=\"user-content-files-modified\" class=\"anchor\" aria-label=\"Permalink: Files Modified\" href=\"#files-modified\"\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\u003eProject\u003c/th\u003e\n\u003cth\u003eFile\u003c/th\u003e\n\u003cth\u003eChanges\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003enullclaw\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003esrc/gateway.zig\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eAdd 3 new endpoints: /api/worker, /api/send, /api/callback\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003enullclaw\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003esrc/config.zig\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eAdd nullboiler config struct\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003enullclaw\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003esrc/daemon.zig\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eAdd self-registration startup hook\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003enullclaw\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003esrc/tools/workflow.zig\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eNew tool for create_workflow\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003enullclaw\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003esrc/tools/root.zig\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eRegister workflow tool\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003enullboiler\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003esrc/api.zig\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eOptionally include telegram_target in run metadata\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003enulltickets\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003esrc/api.zig\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eOptional: webhook subscriptions (low priority)\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\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eReferences\u003c/h2\u003e\u003ca id=\"user-content-references\" class=\"anchor\" aria-label=\"Permalink: References\" href=\"#references\"\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=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003enullclaw\u003c/h3\u003e\u003ca id=\"user-content-nullclaw\" class=\"anchor\" aria-label=\"Permalink: nullclaw\" href=\"#nullclaw\"\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\u003ccode\u003esrc/gateway.zig\u003c/code\u003e - HTTP server and routing\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esrc/agent/root.zig\u003c/code\u003e - Agent execution\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esrc/session.zig\u003c/code\u003e - Session management\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esrc/agent_bindings_config.zig\u003c/code\u003e - Topic binding resolution\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esrc/tools/message.zig\u003c/code\u003e - Message sending\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esrc/channels/telegram.zig\u003c/code\u003e - Telegram topic support\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003enullboiler\u003c/h3\u003e\u003ca id=\"user-content-nullboiler\" class=\"anchor\" aria-label=\"Permalink: nullboiler\" href=\"#nullboiler\"\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\u003ccode\u003esrc/engine.zig\u003c/code\u003e - DAG execution loop\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esrc/dispatch.zig\u003c/code\u003e - Worker dispatch logic\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esrc/callbacks.zig\u003c/code\u003e - Callback firing mechanism\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esrc/api.zig\u003c/code\u003e - REST API endpoints\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esrc/types.zig\u003c/code\u003e - Step types and data structures\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003enulltickets\u003c/h3\u003e\u003ca id=\"user-content-nulltickets\" class=\"anchor\" aria-label=\"Permalink: nulltickets\" href=\"#nulltickets\"\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\u003ccode\u003esrc/api.zig\u003c/code\u003e - REST API\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esrc/store.zig\u003c/code\u003e - Database operations\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esrc/domain.zig\u003c/code\u003e - FSM transitions\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eVersion History\u003c/h2\u003e\u003ca id=\"user-content-version-history\" class=\"anchor\" aria-label=\"Permalink: Version History\" href=\"#version-history\"\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\u003eDate\u003c/th\u003e\n\u003cth\u003eAuthor\u003c/th\u003e\n\u003cth\u003eChanges\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e2026-03-13\u003c/td\u003e\n\u003ctd\u003e@vedmalex\u003c/td\u003e\n\u003ctd\u003eInitial gap analysis based on codebase exploration\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003chr\u003e\n\u003cp dir=\"auto\"\u003e\u003cem\u003eThis document is a living analysis. As implementations progress, update the status of each gap and add implementation notes.\u003c/em\u003e\u003c/p\u003e\n\u003c/article\u003e","richTextTruncated":false,"renderedFileInfo":null,"symbols":{"timed_out":false,"not_analyzed":false,"symbols":[{"name":"Integration Analysis: nullclaw + nullboiler + nulltickets","fully_qualified_name":"Integration Analysis: nullclaw + nullboiler + nulltickets","kind":"section_1","ident_start":2,"ident_end":59,"extent_start":0,"extent_end":14943,"ident_utf16":{"start":{"line_number":0,"utf16_col":2},"end":{"line_number":0,"utf16_col":59}},"extent_utf16":{"start":{"line_number":0,"utf16_col":0},"end":{"line_number":489,"utf16_col":0}}},{"name":"Executive Summary","fully_qualified_name":"Executive Summary","kind":"section_2","ident_start":64,"ident_end":81,"extent_start":61,"extent_end":441,"ident_utf16":{"start":{"line_number":2,"utf16_col":3},"end":{"line_number":2,"utf16_col":20}},"extent_utf16":{"start":{"line_number":2,"utf16_col":0},"end":{"line_number":9,"utf16_col":0}}},{"name":"Architecture Overview","fully_qualified_name":"Architecture Overview","kind":"section_2","ident_start":444,"ident_end":465,"extent_start":441,"extent_end":1859,"ident_utf16":{"start":{"line_number":9,"utf16_col":3},"end":{"line_number":9,"utf16_col":24}},"extent_utf16":{"start":{"line_number":9,"utf16_col":0},"end":{"line_number":31,"utf16_col":0}}},{"name":"Project Roles","fully_qualified_name":"Project Roles","kind":"section_3","ident_start":1361,"ident_end":1374,"extent_start":1357,"extent_end":1859,"ident_utf16":{"start":{"line_number":23,"utf16_col":4},"end":{"line_number":23,"utf16_col":17}},"extent_utf16":{"start":{"line_number":23,"utf16_col":0},"end":{"line_number":31,"utf16_col":0}}},{"name":"Current Capabilities","fully_qualified_name":"Current Capabilities","kind":"section_2","ident_start":1862,"ident_end":1882,"extent_start":1859,"extent_end":3160,"ident_utf16":{"start":{"line_number":31,"utf16_col":3},"end":{"line_number":31,"utf16_col":23}},"extent_utf16":{"start":{"line_number":31,"utf16_col":0},"end":{"line_number":60,"utf16_col":0}}},{"name":"✅ What Already Works","fully_qualified_name":"✅ What Already Works","kind":"section_3","ident_start":1888,"ident_end":1910,"extent_start":1884,"extent_end":3160,"ident_utf16":{"start":{"line_number":33,"utf16_col":4},"end":{"line_number":33,"utf16_col":24}},"extent_utf16":{"start":{"line_number":33,"utf16_col":0},"end":{"line_number":60,"utf16_col":0}}},{"name":"Integration Gaps","fully_qualified_name":"Integration Gaps","kind":"section_2","ident_start":3163,"ident_end":3179,"extent_start":3160,"extent_end":8846,"ident_utf16":{"start":{"line_number":60,"utf16_col":3},"end":{"line_number":60,"utf16_col":19}},"extent_utf16":{"start":{"line_number":60,"utf16_col":0},"end":{"line_number":243,"utf16_col":0}}},{"name":"Gap 1: External Message Send API (HIGH PRIORITY)","fully_qualified_name":"Gap 1: External Message Send API (HIGH PRIORITY)","kind":"section_3","ident_start":3185,"ident_end":3233,"extent_start":3181,"extent_end":4076,"ident_utf16":{"start":{"line_number":62,"utf16_col":4},"end":{"line_number":62,"utf16_col":52}},"extent_utf16":{"start":{"line_number":62,"utf16_col":0},"end":{"line_number":88,"utf16_col":0}}},{"name":"Gap 2: Callback Receiver for nullboiler (HIGH PRIORITY)","fully_qualified_name":"Gap 2: Callback Receiver for nullboiler (HIGH PRIORITY)","kind":"section_3","ident_start":4080,"ident_end":4135,"extent_start":4076,"extent_end":4871,"ident_utf16":{"start":{"line_number":88,"utf16_col":4},"end":{"line_number":88,"utf16_col":59}},"extent_utf16":{"start":{"line_number":88,"utf16_col":0},"end":{"line_number":114,"utf16_col":0}}},{"name":"Gap 3: Worker Endpoint for nullboiler Dispatch (HIGH PRIORITY)","fully_qualified_name":"Gap 3: Worker Endpoint for nullboiler Dispatch (HIGH PRIORITY)","kind":"section_3","ident_start":4875,"ident_end":4937,"extent_start":4871,"extent_end":6023,"ident_utf16":{"start":{"line_number":114,"utf16_col":4},"end":{"line_number":114,"utf16_col":66}},"extent_utf16":{"start":{"line_number":114,"utf16_col":0},"end":{"line_number":148,"utf16_col":0}}},{"name":"Gap 4: Self-Registration with nullboiler (MEDIUM PRIORITY)","fully_qualified_name":"Gap 4: Self-Registration with nullboiler (MEDIUM PRIORITY)","kind":"section_3","ident_start":6027,"ident_end":6085,"extent_start":6023,"extent_end":6804,"ident_utf16":{"start":{"line_number":148,"utf16_col":4},"end":{"line_number":148,"utf16_col":62}},"extent_utf16":{"start":{"line_number":148,"utf16_col":0},"end":{"line_number":173,"utf16_col":0}}},{"name":"Gap 5: Dedicated Workflow Tool (MEDIUM PRIORITY)","fully_qualified_name":"Gap 5: Dedicated Workflow Tool (MEDIUM PRIORITY)","kind":"section_3","ident_start":6808,"ident_end":6856,"extent_start":6804,"extent_end":7600,"ident_utf16":{"start":{"line_number":173,"utf16_col":4},"end":{"line_number":173,"utf16_col":52}},"extent_utf16":{"start":{"line_number":173,"utf16_col":0},"end":{"line_number":201,"utf16_col":0}}},{"name":"Gap 6: Topic-Aware Callback Routing (MEDIUM PRIORITY)","fully_qualified_name":"Gap 6: Topic-Aware Callback Routing (MEDIUM PRIORITY)","kind":"section_3","ident_start":7604,"ident_end":7657,"extent_start":7600,"extent_end":8362,"ident_utf16":{"start":{"line_number":201,"utf16_col":4},"end":{"line_number":201,"utf16_col":57}},"extent_utf16":{"start":{"line_number":201,"utf16_col":0},"end":{"line_number":229,"utf16_col":0}}},{"name":"Gap 7: nulltickets Push Notifications (LOW PRIORITY)","fully_qualified_name":"Gap 7: nulltickets Push Notifications (LOW PRIORITY)","kind":"section_3","ident_start":8366,"ident_end":8418,"extent_start":8362,"extent_end":8846,"ident_utf16":{"start":{"line_number":229,"utf16_col":4},"end":{"line_number":229,"utf16_col":56}},"extent_utf16":{"start":{"line_number":229,"utf16_col":0},"end":{"line_number":243,"utf16_col":0}}},{"name":"Implementation Roadmap","fully_qualified_name":"Implementation Roadmap","kind":"section_2","ident_start":8849,"ident_end":8871,"extent_start":8846,"extent_end":10431,"ident_utf16":{"start":{"line_number":243,"utf16_col":3},"end":{"line_number":243,"utf16_col":25}},"extent_utf16":{"start":{"line_number":243,"utf16_col":0},"end":{"line_number":300,"utf16_col":0}}},{"name":"Phase 1: Critical Path (Gaps 1-3)","fully_qualified_name":"Phase 1: Critical Path (Gaps 1-3)","kind":"section_3","ident_start":8877,"ident_end":8910,"extent_start":8873,"extent_end":9563,"ident_utf16":{"start":{"line_number":245,"utf16_col":4},"end":{"line_number":245,"utf16_col":37}},"extent_utf16":{"start":{"line_number":245,"utf16_col":0},"end":{"line_number":267,"utf16_col":0}}},{"name":"Phase 2: Feedback Loop (Gaps 2+6)","fully_qualified_name":"Phase 2: Feedback Loop (Gaps 2+6)","kind":"section_3","ident_start":9567,"ident_end":9600,"extent_start":9563,"extent_end":9887,"ident_utf16":{"start":{"line_number":267,"utf16_col":4},"end":{"line_number":267,"utf16_col":37}},"extent_utf16":{"start":{"line_number":267,"utf16_col":0},"end":{"line_number":277,"utf16_col":0}}},{"name":"Phase 3: Automation (Gap 4)","fully_qualified_name":"Phase 3: Automation (Gap 4)","kind":"section_3","ident_start":9891,"ident_end":9918,"extent_start":9887,"extent_end":10068,"ident_utf16":{"start":{"line_number":277,"utf16_col":4},"end":{"line_number":277,"utf16_col":31}},"extent_utf16":{"start":{"line_number":277,"utf16_col":0},"end":{"line_number":285,"utf16_col":0}}},{"name":"Phase 4: Usability (Gap 5)","fully_qualified_name":"Phase 4: Usability (Gap 5)","kind":"section_3","ident_start":10072,"ident_end":10098,"extent_start":10068,"extent_end":10265,"ident_utf16":{"start":{"line_number":285,"utf16_col":4},"end":{"line_number":285,"utf16_col":30}},"extent_utf16":{"start":{"line_number":285,"utf16_col":0},"end":{"line_number":293,"utf16_col":0}}},{"name":"Phase 5: Enhancement (Gap 7)","fully_qualified_name":"Phase 5: Enhancement (Gap 7)","kind":"section_3","ident_start":10269,"ident_end":10297,"extent_start":10265,"extent_end":10431,"ident_utf16":{"start":{"line_number":293,"utf16_col":4},"end":{"line_number":293,"utf16_col":32}},"extent_utf16":{"start":{"line_number":293,"utf16_col":0},"end":{"line_number":300,"utf16_col":0}}},{"name":"Technical Details","fully_qualified_name":"Technical Details","kind":"section_2","ident_start":10434,"ident_end":10451,"extent_start":10431,"extent_end":12992,"ident_utf16":{"start":{"line_number":300,"utf16_col":3},"end":{"line_number":300,"utf16_col":20}},"extent_utf16":{"start":{"line_number":300,"utf16_col":0},"end":{"line_number":426,"utf16_col":0}}},{"name":"nullclaw Gateway API Design","fully_qualified_name":"nullclaw Gateway API Design","kind":"section_3","ident_start":10457,"ident_end":10484,"extent_start":10453,"extent_end":11619,"ident_utf16":{"start":{"line_number":302,"utf16_col":4},"end":{"line_number":302,"utf16_col":31}},"extent_utf16":{"start":{"line_number":302,"utf16_col":0},"end":{"line_number":369,"utf16_col":0}}},{"name":"nullboiler Integration Points","fully_qualified_name":"nullboiler Integration Points","kind":"section_3","ident_start":11623,"ident_end":11652,"extent_start":11619,"extent_end":12068,"ident_utf16":{"start":{"line_number":369,"utf16_col":4},"end":{"line_number":369,"utf16_col":33}},"extent_utf16":{"start":{"line_number":369,"utf16_col":0},"end":{"line_number":388,"utf16_col":0}}},{"name":"Data Flow Example","fully_qualified_name":"Data Flow Example","kind":"section_3","ident_start":12072,"ident_end":12089,"extent_start":12068,"extent_end":12992,"ident_utf16":{"start":{"line_number":388,"utf16_col":4},"end":{"line_number":388,"utf16_col":21}},"extent_utf16":{"start":{"line_number":388,"utf16_col":0},"end":{"line_number":426,"utf16_col":0}}},{"name":"Configuration Example","fully_qualified_name":"Configuration Example","kind":"section_2","ident_start":12995,"ident_end":13016,"extent_start":12992,"extent_end":13376,"ident_utf16":{"start":{"line_number":426,"utf16_col":3},"end":{"line_number":426,"utf16_col":24}},"extent_utf16":{"start":{"line_number":426,"utf16_col":0},"end":{"line_number":446,"utf16_col":0}}},{"name":"Files Modified","fully_qualified_name":"Files Modified","kind":"section_2","ident_start":13379,"ident_end":13393,"extent_start":13376,"extent_end":13977,"ident_utf16":{"start":{"line_number":446,"utf16_col":3},"end":{"line_number":446,"utf16_col":17}},"extent_utf16":{"start":{"line_number":446,"utf16_col":0},"end":{"line_number":458,"utf16_col":0}}},{"name":"References","fully_qualified_name":"References","kind":"section_2","ident_start":13980,"ident_end":13990,"extent_start":13977,"extent_end":14654,"ident_utf16":{"start":{"line_number":458,"utf16_col":3},"end":{"line_number":458,"utf16_col":13}},"extent_utf16":{"start":{"line_number":458,"utf16_col":0},"end":{"line_number":480,"utf16_col":0}}},{"name":"nullclaw","fully_qualified_name":"nullclaw","kind":"section_3","ident_start":13996,"ident_end":14004,"extent_start":13992,"extent_end":14294,"ident_utf16":{"start":{"line_number":460,"utf16_col":4},"end":{"line_number":460,"utf16_col":12}},"extent_utf16":{"start":{"line_number":460,"utf16_col":0},"end":{"line_number":468,"utf16_col":0}}},{"name":"nullboiler","fully_qualified_name":"nullboiler","kind":"section_3","ident_start":14298,"ident_end":14308,"extent_start":14294,"extent_end":14533,"ident_utf16":{"start":{"line_number":468,"utf16_col":4},"end":{"line_number":468,"utf16_col":14}},"extent_utf16":{"start":{"line_number":468,"utf16_col":0},"end":{"line_number":475,"utf16_col":0}}},{"name":"nulltickets","fully_qualified_name":"nulltickets","kind":"section_3","ident_start":14537,"ident_end":14548,"extent_start":14533,"extent_end":14654,"ident_utf16":{"start":{"line_number":475,"utf16_col":4},"end":{"line_number":475,"utf16_col":15}},"extent_utf16":{"start":{"line_number":475,"utf16_col":0},"end":{"line_number":480,"utf16_col":0}}},{"name":"Version History","fully_qualified_name":"Version History","kind":"section_2","ident_start":14657,"ident_end":14672,"extent_start":14654,"extent_end":14943,"ident_utf16":{"start":{"line_number":480,"utf16_col":3},"end":{"line_number":480,"utf16_col":18}},"extent_utf16":{"start":{"line_number":480,"utf16_col":0},"end":{"line_number":489,"utf16_col":0}}}]}},"codeViewLayoutRoute":{"repo":{"id":1159542259,"defaultBranch":"main","name":"nullclaw","ownerLogin":"nullclaw","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2026-02-16T21:17:27.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/262007611?v=4","public":true,"private":false,"isOrgOwned":true,"isArchived":false},"currentUser":null,"uploadToken":"XZu6qAvikF8j-mSleTSKe61dhpeFCKXP8rd-fVX2QMPZ2g8ZDlEitpKwaGMEJnifgMmShSnJ49EjWQhBwPKWXQ","allShortcutsEnabled":false,"treeExpanded":true,"path":"docs/integration-analysis.md","symbolsExpanded":false,"refInfo":{"name":"main","listCacheKey":"v0:1791453467.0","canEdit":false,"currentOid":"5f1cade05c19b6ecdfb9565ae3305e892e484da9"},"helpUrl":"https://docs.github.com","githubDevUrl":null},"codeViewFileTreeLayoutRoute":{"fileTree":{"docs":{"items":[{"name":"en","path":"docs/en","contentType":"directory"},{"name":"zh","path":"docs/zh","contentType":"directory"},{"name":"README.md","path":"docs/README.md","contentType":"file"},{"name":"integration-analysis.md","path":"docs/integration-analysis.md","contentType":"file"},{"name":"integration-roadmap.md","path":"docs/integration-roadmap.md","contentType":"file"}],"totalCount":5},"":{"items":[{"name":".githooks","path":".githooks","contentType":"directory"},{"name":".github","path":".github","contentType":"directory"},{"name":"docs","path":"docs","contentType":"directory"},{"name":"examples","path":"examples","contentType":"directory"},{"name":"spec","path":"spec","contentType":"directory"},{"name":"src","path":"src","contentType":"directory"},{"name":"vendor","path":"vendor","contentType":"directory"},{"name":".dockerignore","path":".dockerignore","contentType":"file"},{"name":".env.example","path":".env.example","contentType":"file"},{"name":".envrc","path":".envrc","contentType":"file"},{"name":".gitignore","path":".gitignore","contentType":"file"},{"name":"AGENTS.md","path":"AGENTS.md","contentType":"file"},{"name":"CLAUDE.md","path":"CLAUDE.md","contentType":"file"},{"name":"CONTRIBUTING.md","path":"CONTRIBUTING.md","contentType":"file"},{"name":"Dockerfile","path":"Dockerfile","contentType":"file"},{"name":"LICENSE","path":"LICENSE","contentType":"file"},{"name":"Makefile","path":"Makefile","contentType":"file"},{"name":"README.md","path":"README.md","contentType":"file"},{"name":"RELEASING.md","path":"RELEASING.md","contentType":"file"},{"name":"SECURITY-PATCH-PLAN-2026-05-10.md","path":"SECURITY-PATCH-PLAN-2026-05-10.md","contentType":"file"},{"name":"SECURITY.md","path":"SECURITY.md","contentType":"file"},{"name":"SIGNAL.md","path":"SIGNAL.md","contentType":"file"},{"name":"build.zig","path":"build.zig","contentType":"file"},{"name":"build.zig.zon","path":"build.zig.zon","contentType":"file"},{"name":"build.zig.zon2json-lock","path":"build.zig.zon2json-lock","contentType":"file"},{"name":"config.example.json","path":"config.example.json","contentType":"file"},{"name":"docker-compose.signal.yml","path":"docker-compose.signal.yml","contentType":"file"},{"name":"docker-compose.yml","path":"docker-compose.yml","contentType":"file"},{"name":"flake.lock","path":"flake.lock","contentType":"file"},{"name":"flake.nix","path":"flake.nix","contentType":"file"},{"name":"nullclaw.png","path":"nullclaw.png","contentType":"file"},{"name":"run","path":"run","contentType":"file"}],"totalCount":32}},"fileTreeProcessingTime":28.766192999999998,"foldersToFetch":[]},"codeViewBlobLayoutRoute":{"codeLineWrapEnabled":false,"refInfo":{"name":"main","listCacheKey":"v0:1791453467.0","canEdit":false,"refType":"branch","currentOid":"5f1cade05c19b6ecdfb9565ae3305e892e484da9","canEditOnDefaultBranch":false,"fileExistsOnDefault":true},"path":"docs/integration-analysis.md","blob":{"copilotSWEAgentEnabled":false,"dependabotInfo":{"showConfigurationBanner":false,"configFilePath":null,"networkDependabotPath":"/nullclaw/nullclaw/network/updates","dismissConfigurationNoticePath":"/settings/dismiss-notice/dependabot_configuration_notice","configurationNoticeDismissed":null},"displayName":"integration-analysis.md","displayUrl":"https://github.com/nullclaw/nullclaw/blob/main/docs/integration-analysis.md?raw=true","headerInfo":{"blobSize":"14.6 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":"64ef14e","siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2Fnullclaw%2Fnullclaw%2Fblob%2Fmain%2Fdocs%2Fintegration-analysis.md","isCSV":false,"isRichtext":true,"lineInfo":{"truncatedLoc":"489","truncatedSloc":"387"},"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":"/nullclaw/nullclaw/blob/main/docs/integration-analysis.md","showFreeOrgGatedFeatureMessage":null,"showPlanSupportBanner":null,"upgradeDataAttributes":null,"upgradePath":null},"publishBannersInfo":{"dismissActionNoticePath":"/settings/dismiss-notice/publish_action_from_dockerfile","releasePath":"/nullclaw/nullclaw/releases/new?marketplace=true","showPublishActionBanner":false},"rawBlobUrl":"https://github.com/nullclaw/nullclaw/raw/refs/heads/main/docs/integration-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":["# Integration Analysis: nullclaw + nullboiler + nulltickets","","## Executive Summary","","This document analyzes the integration gaps between three nullclaw ecosystem projects to enable end-to-end multi-agent workflows with Telegram topic routing.","","**Target Scenario:**","\u003e User sends message in Telegram General topic → Orchestrator agent decides to delegate coding task → Coder agent executes → Result appears in the Coder topic in Telegram","","## Architecture Overview","","```","┌─────────────────┐     ┌──────────────────┐     ┌─────────────────┐","│   nulltickets   │────▶│   nullboiler     │────▶│    nullclaw     │","│  (Task Tracker) │     │ (DAG Orchestrator)│     │  (AI Runtime)   │","└─────────────────┘     └──────────────────┘     └─────────────────┘","         │                       │                       │","         ▼                       ▼                       ▼","   Pipeline FSM             Workflow DAG           Telegram Topics","   Lease-based              Step dispatch          Agent routing","   Role routing             Worker selection       Tool execution","```","","### Project Roles","","| Component | Responsibility | Key Files |","|-----------|---------------|-----------|","| **nulltickets** | Durable task state, FSM transitions, lease coordination | `src/api.zig`, `src/store.zig`, `src/domain.zig` |","| **nullboiler** | DAG scheduling, worker dispatch, step orchestration | `src/engine.zig`, `src/dispatch.zig`, `src/callbacks.zig` |","| **nullclaw** | AI agent runtime, tool execution, Telegram integration | `src/agent/root.zig`, `src/gateway.zig`, `src/session.zig` |","","## Current Capabilities","","### ✅ What Already Works","","1. **Telegram Topic Delivery** (`nullclaw/src/channels/telegram.zig:146-156`)","   - Supports `chatid#topic:threadid` format for forum topics","   - `MessageTool` can send to any channel/topic combination","","2. **Agent Routing per Topic** (`nullclaw/src/agent_bindings_config.zig`)","   - 7-tier binding system: peer → parent_peer → guild_roles → guild → team → account → default","   - `/bind` command for runtime topic-to-agent binding","","3. **nullboiler Callback System** (`nullboiler/src/callbacks.zig:21-114`)","   - Webhook callbacks on events: `step.completed`, `step.failed`, `run.completed`, `run.failed`","   - Supports custom headers and HMAC signing","","4. **nullboiler Worker Dispatch** (`nullboiler/src/dispatch.zig:89-199`)","   - 5 protocols: webhook, api_chat, openai_chat, mqtt, redis_stream","   - Tag-based worker selection with least-loaded balancing","","5. **nullclaw Tool System** (`nullclaw/src/tools/root.zig`)","   - `MessageTool` — send to any channel/topic internally","   - `DelegateTool` — synchronous sub-agent delegation","   - `HttpRequestTool` — arbitrary HTTP calls","","6. **Agent Profile System** (`nullclaw/src/config.zig`)","   - Named agents with different providers, models, system prompts","   - Session-scoped agent instances","","## Integration Gaps","","### Gap 1: External Message Send API (HIGH PRIORITY)","","**Problem:** nullclaw's gateway is inbound-only. No endpoint exists for external services (like nullboiler) to trigger outbound messages to specific Telegram topics.","","**Current State:**","- Gateway endpoints: `/health`, `/ready`, `/pair`, `/webhook`, `/telegram`, `/whatsapp`, `/a2a`","- No `/api/send` or similar endpoint","","**Required:**","- New `POST /api/send` endpoint in `nullclaw/src/gateway.zig`","- Accept JSON: `{channel: \"telegram\", chat_id: \"-100123#topic:456\", content: \"...\"}`","- Hook into `bus.Bus.publishOutbound()` for delivery","- Authentication via existing token/pairing system","","**Implementation Notes:**","```zig","// Potential endpoint structure in gateway.zig","POST /api/send","Body: {","  \"channel\": \"telegram\",","  \"chat_id\": \"-1001234567890#topic:42\",","  \"content\": \"Coder agent completed the task...\",","  \"reply_to_message_id\": null","}","```","","### Gap 2: Callback Receiver for nullboiler (HIGH PRIORITY)","","**Problem:** nullboiler can fire callbacks when steps complete, but nullclaw has no endpoint to receive them.","","**Current State:**","- nullboiler fires callbacks: `fireCallbacks()` in `nullboiler/src/callbacks.zig:21-114`","- Callback format: `{event, run_id, step_id, output, status}`","- nullclaw has no `/api/callback` endpoint","","**Required:**","- New `POST /api/callback` endpoint in `nullclaw/src/gateway.zig`","- Parse nullboiler callback format","- Route results to appropriate Telegram topic via outbound bus","","**Implementation Notes:**","```zig","// Callback format from nullboiler/src/callbacks.zig","{","  \"event\": \"step.completed\",","  \"run_id\": \"run-uuid\",","  \"step_id\": \"code\",","  \"output\": \"The generated bash script...\",","  \"status\": \"ok\"","}","```","","### Gap 3: Worker Endpoint for nullboiler Dispatch (HIGH PRIORITY)","","**Problem:** nullboiler dispatches steps to workers via HTTP POST, but nullclaw has no endpoint that accepts nullboiler's step format.","","**Current State:**","- nullboiler dispatches: `dispatchStep()` in `nullboiler/src/dispatch.zig:89-199`","- Dispatch payload: `{prompt, context, step_id, run_id, correlation_id}`","- nullclaw's `/webhook` is designed for Telegram, not generic worker tasks","","**Required:**","- New `POST /api/worker` endpoint in `nullclaw/src/gateway.zig`","- Accept nullboiler step dispatch format","- Route to appropriate agent via `agent_routing.resolveRoute()`","- Return response in format: `{status:\"ok\", response:\"...\"}`","- Handle via `session_mgr.processMessage()` for agent execution","","**Implementation Notes:**","```zig","// Worker dispatch payload from nullboiler","{","  \"prompt\": \"Generate a bash script that...\",","  \"context\": {\"previous_output\": \"...\"},","  \"step_id\": \"code\",","  \"run_id\": \"run-uuid\",","  \"correlation_id\": \"corr-uuid\"","}","","// Expected response format (nullboiler/src/worker_response.zig:102)","{","  \"status\": \"ok\",","  \"response\": \"#!/bin/bash\\necho 'Hello World'\"","}","```","","### Gap 4: Self-Registration with nullboiler (MEDIUM PRIORITY)","","**Problem:** nullclaw cannot automatically register itself as a nullboiler worker on startup.","","**Current State:**","- nullboiler has `POST /workers` endpoint (`nullboiler/src/api.zig:135`)","- nullclaw has no startup registration logic","","**Required:**","- Config additions: `nullboiler.url`, `nullboiler.worker_id`, `nullboiler.tags`, `nullboiler.capacity`","- Startup hook in `nullclaw/src/daemon.zig` or new `nullclaw/src/boiler_client.zig`","- HTTP POST to `{nullboiler_url}/workers` with registration payload","","**Implementation Notes:**","```zig","// Registration payload","{","  \"id\": \"nullclaw-coder-1\",","  \"url\": \"http://nullclaw:8080/api/worker\",","  \"protocol\": \"webhook\",","  \"tags\": [\"coder\", \"bash\"],","  \"max_concurrent\": 3","}","```","","### Gap 5: Dedicated Workflow Tool (MEDIUM PRIORITY)","","**Problem:** Orchestrator agent must manually construct nullboiler API calls using `http_request` tool, which is error-prone.","","**Current State:**","- nullboiler `POST /runs` endpoint exists (`nullboiler/src/api.zig:70`)","- nullclaw `http_request` tool can make arbitrary calls","- No high-level workflow abstraction","","**Required:**","- New `create_workflow` tool in `nullclaw/src/tools/workflow.zig`","- Wrap nullboiler `POST /runs` API","- Auto-set callback URL to nullclaw's gateway","- Simplified interface for agent","","**Implementation Notes:**","```zig","// Tool interface","{","  \"name\": \"create_workflow\",","  \"arguments\": {","    \"workflow_name\": \"code-review\",","    \"inputs\": {\"task\": \"Create bash script\"},","    \"telegram_target\": \"-100123#topic:456\"","  }","}","```","","### Gap 6: Topic-Aware Callback Routing (MEDIUM PRIORITY)","","**Problem:** When nullboiler sends a callback, nullclaw needs to know which Telegram topic to route the result to.","","**Current State:**","- Callbacks contain run/step metadata but no Telegram routing info","- Agent bindings config has topic mappings","","**Required:**","- Store `telegram_target` (chat_id#topic) in run metadata when creating workflow","- Include in callback payload or correlate via run_id","- Callback receiver looks up target and routes via outbound bus","","**Implementation Notes:**","```zig","// Store in run creation","POST /runs","{","  \"workflow\": {...},","  \"inputs\": {...},","  \"metadata\": {","    \"telegram_target\": \"-100123#topic:456\",","    \"origin_chat_id\": \"-100123\",","    \"origin_topic_id\": \"42\"","  }","}","```","","### Gap 7: nulltickets Push Notifications (LOW PRIORITY)","","**Problem:** nulltickets is pull-based (lease/claim). No push/webhook mechanism for real-time notifications.","","**Current State:**","- nulltickets API: claim tasks via `POST /leases/claim`","- No webhook subscription endpoint","","**Impact:** Low — nullboiler already bridges via `tracker_client.zig` polling","","**Required (if needed):**","- New webhook subscription API in `nulltickets/src/api.zig`","- Fire webhooks on stage transitions","","## Implementation Roadmap","","### Phase 1: Critical Path (Gaps 1-3)","","Without these, nullboiler cannot communicate with nullclaw at all.","","1. **Worker Endpoint** (`POST /api/worker`)","   - Accept nullboiler step dispatch","   - Route to agent via session manager","   - Return synchronous response","   - File: `nullclaw/src/gateway.zig`","","2. **External Send API** (`POST /api/send`)","   - Accept authenticated requests to send messages","   - Hook into outbound bus","   - Support topic format `chatid#topic:threadid`","   - File: `nullclaw/src/gateway.zig`","","3. **Callback Receiver** (`POST /api/callback`)","   - Accept nullboiler callbacks","   - Parse event types","   - Route to appropriate handler","   - File: `nullclaw/src/gateway.zig`","","### Phase 2: Feedback Loop (Gaps 2+6)","","Close the loop so workflow results reach the right Telegram topic.","","4. **Topic-Aware Routing**","   - Store telegram_target in run metadata","   - Callback receiver extracts and routes","   - Integration with agent bindings","   - Files: `nullclaw/src/gateway.zig`, `nullboiler` run creation","","### Phase 3: Automation (Gap 4)","","5. **Self-Registration**","   - Config schema additions","   - Startup registration logic","   - Health check pings","   - File: `nullclaw/src/daemon.zig`","","### Phase 4: Usability (Gap 5)","","6. **Workflow Tool**","   - High-level tool for orchestrator agents","   - Auto-configure callbacks","   - Schema validation","   - File: `nullclaw/src/tools/workflow.zig`","","### Phase 5: Enhancement (Gap 7)","","7. **nulltickets Push** (optional)","   - Webhook subscription API","   - Stage transition events","   - File: `nulltickets/src/api.zig`","","## Technical Details","","### nullclaw Gateway API Design","","```zig","// New endpoints to add in nullclaw/src/gateway.zig","","// 1. Worker endpoint for nullboiler dispatch","POST /api/worker","Content-Type: application/json","Authorization: Bearer \u003ctoken\u003e","","Request:","{","  \"prompt\": \"Generate a bash script that...\",","  \"context\": {\"previous_output\": \"...\"},","  \"step_id\": \"code\",","  \"run_id\": \"run-uuid\",","  \"correlation_id\": \"corr-uuid\"","}","","Response:","{","  \"status\": \"ok\",","  \"response\": \"#!/bin/bash\\necho 'Hello World'\",","  \"correlation_id\": \"corr-uuid\"","}","","// 2. External message send","POST /api/send","Content-Type: application/json","Authorization: Bearer \u003ctoken\u003e","","Request:","{","  \"channel\": \"telegram\",","  \"chat_id\": \"-1001234567890#topic:42\",","  \"content\": \"Task completed successfully!\",","  \"reply_to_message_id\": null","}","","Response:","{","  \"status\": \"ok\",","  \"message_id\": \"12345\"","}","","// 3. Callback receiver","POST /api/callback","Content-Type: application/json","Authorization: Bearer \u003ctoken\u003e","","Request:","{","  \"event\": \"step.completed\",","  \"run_id\": \"run-uuid\",","  \"step_id\": \"code\",","  \"output\": \"Generated script content...\",","  \"metadata\": {","    \"telegram_target\": \"-100123#topic:42\"","  }","}","","Response:","{","  \"status\": \"received\"","}","```","","### nullboiler Integration Points","","```zig","// nullboiler/src/callbacks.zig - existing callback firing","// This already works, just needs a target endpoint","","pub fn fireCallbacks(","    allocator: std.mem.Allocator,","    callbacks: []const Callback,","    event: Event,","    run_id: []const u8,","    step_id: ?[]const u8,","    output: ?[]const u8,",") !void {","    // Callback POST to nullclaw /api/callback","    // Include telegram_target from run metadata","}","```","","### Data Flow Example","","```","User in General topic:","  \"Write a bash script that backs up my home directory\"","","1. nullclaw receives via Telegram webhook","2. Agent \"orchestrator\" processes message","3. Agent calls create_workflow tool","   → POST to nullboiler /runs","   → Metadata includes: telegram_target=\"general#topic:1\"","","nullboiler:","4. Creates workflow run","5. Dispatches \"code\" step to \"coder\" worker (nullclaw instance)","   → POST to nullclaw /api/worker","","nullclaw (coder):","6. Receives step dispatch","7. Agent \"coder\" generates script","8. Returns response to nullboiler","","nullboiler:","9. Step completes","10. Fires callback","    → POST to nullclaw /api/callback","    → Includes output + telegram_target","","nullclaw:","11. Callback receiver parses event","12. Routes output to telegram_target","    → POST internally to /api/send","    → Delivers to General topic","","User sees:","  [In General topic] \"Here's the backup script: ...\"","```","","## Configuration Example","","```json","// nullclaw config.json additions","{","  \"nullboiler\": {","    \"url\": \"http://nullboiler:8080\",","    \"worker_id\": \"nullclaw-main\",","    \"tags\": [\"orchestrator\", \"general\"],","    \"max_concurrent\": 5,","    \"auto_register\": true","  },","  \"gateway\": {","    \"enable_worker_endpoint\": true,","    \"enable_callback_endpoint\": true,","    \"enable_send_api\": true","  }","}","```","","## Files Modified","","| Project | File | Changes |","|---------|------|---------|","| nullclaw | `src/gateway.zig` | Add 3 new endpoints: /api/worker, /api/send, /api/callback |","| nullclaw | `src/config.zig` | Add nullboiler config struct |","| nullclaw | `src/daemon.zig` | Add self-registration startup hook |","| nullclaw | `src/tools/workflow.zig` | New tool for create_workflow |","| nullclaw | `src/tools/root.zig` | Register workflow tool |","| nullboiler | `src/api.zig` | Optionally include telegram_target in run metadata |","| nulltickets | `src/api.zig` | Optional: webhook subscriptions (low priority) |","","## References","","### nullclaw","- `src/gateway.zig` - HTTP server and routing","- `src/agent/root.zig` - Agent execution","- `src/session.zig` - Session management","- `src/agent_bindings_config.zig` - Topic binding resolution","- `src/tools/message.zig` - Message sending","- `src/channels/telegram.zig` - Telegram topic support","","### nullboiler","- `src/engine.zig` - DAG execution loop","- `src/dispatch.zig` - Worker dispatch logic","- `src/callbacks.zig` - Callback firing mechanism","- `src/api.zig` - REST API endpoints","- `src/types.zig` - Step types and data structures","","### nulltickets","- `src/api.zig` - REST API","- `src/store.zig` - Database operations","- `src/domain.zig` - FSM transitions","","## Version History","","| Date | Author | Changes |","|------|--------|---------|","| 2026-03-13 | @vedmalex | Initial gap analysis based on codebase exploration |","","---","","*This document is a living analysis. As implementations progress, update the status of each gap and add implementation notes.*"],"stylingDirectives":[[[0,59,"pl-mh"],[2,59,"pl-en"]],[],[[0,20,"pl-mh"],[3,20,"pl-en"]],[],[],[],[[0,2,"pl-s"],[18,20,"pl-s"]],[[0,170,"pl-ent"],[0,2,"pl-ent"]],[[0,0,"pl-ent"]],[[0,24,"pl-mh"],[3,24,"pl-en"]],[],[[0,3,"pl-s"],[3,3,"pl-c1"]],[[0,68,"pl-c1"]],[[0,68,"pl-c1"]],[[0,69,"pl-c1"]],[[0,68,"pl-c1"]],[[0,58,"pl-c1"]],[[0,58,"pl-c1"]],[[0,66,"pl-c1"]],[[0,64,"pl-c1"]],[[0,65,"pl-c1"]],[[0,0,"pl-c1"],[0,3,"pl-s"]],[],[[0,17,"pl-mh"],[4,17,"pl-en"]],[],[[0,1,"pl-ml"],[12,13,"pl-ml"],[29,30,"pl-ml"],[41,42,"pl-ml"]],[[0,1,"pl-ml"],[12,13,"pl-ml"],[28,29,"pl-ml"],[40,41,"pl-ml"]],[[0,1,"pl-ml"],[2,4,"pl-s"],[15,17,"pl-s"],[18,19,"pl-ml"],[76,77,"pl-ml"],[78,79,"pl-s"],[79,90,"pl-c1"],[90,91,"pl-s"],[93,94,"pl-s"],[94,107,"pl-c1"],[107,108,"pl-s"],[110,111,"pl-s"],[111,125,"pl-c1"],[125,126,"pl-s"],[127,128,"pl-ml"]],[[0,1,"pl-ml"],[2,4,"pl-s"],[14,16,"pl-s"],[17,18,"pl-ml"],[71,72,"pl-ml"],[73,74,"pl-s"],[74,88,"pl-c1"],[88,89,"pl-s"],[91,92,"pl-s"],[92,108,"pl-c1"],[108,109,"pl-s"],[111,112,"pl-s"],[112,129,"pl-c1"],[129,130,"pl-s"],[131,132,"pl-ml"]],[[0,1,"pl-ml"],[2,4,"pl-s"],[12,14,"pl-s"],[15,16,"pl-ml"],[72,73,"pl-ml"],[74,75,"pl-s"],[75,93,"pl-c1"],[93,94,"pl-s"],[96,97,"pl-s"],[97,112,"pl-c1"],[112,113,"pl-s"],[115,116,"pl-s"],[116,131,"pl-c1"],[131,132,"pl-s"],[133,134,"pl-ml"]],[],[[0,23,"pl-mh"],[3,23,"pl-en"]],[],[[0,24,"pl-mh"],[4,24,"pl-en"]],[],[[0,1,"pl-s"],[1,2,"pl-v"],[3,5,"pl-s"],[28,30,"pl-s"],[32,33,"pl-s"],[33,75,"pl-c1"],[75,76,"pl-s"]],[[3,4,"pl-v"],[14,15,"pl-s"],[15,36,"pl-c1"],[36,37,"pl-s"]],[[3,4,"pl-v"],[5,6,"pl-s"],[6,17,"pl-c1"],[17,18,"pl-s"]],[],[[0,1,"pl-s"],[1,2,"pl-v"],[3,5,"pl-s"],[28,30,"pl-s"],[32,33,"pl-s"],[33,71,"pl-c1"],[71,72,"pl-s"]],[[3,4,"pl-v"]],[[3,4,"pl-v"],[5,6,"pl-s"],[6,11,"pl-c1"],[11,12,"pl-s"]],[],[[0,1,"pl-s"],[1,2,"pl-v"],[3,5,"pl-s"],[31,33,"pl-s"],[35,36,"pl-s"],[36,71,"pl-c1"],[71,72,"pl-s"]],[[3,4,"pl-v"],[34,35,"pl-s"],[35,49,"pl-c1"],[49,50,"pl-s"],[52,53,"pl-s"],[53,64,"pl-c1"],[64,65,"pl-s"],[67,68,"pl-s"],[68,81,"pl-c1"],[81,82,"pl-s"],[84,85,"pl-s"],[85,95,"pl-c1"],[95,96,"pl-s"]],[[3,4,"pl-v"]],[],[[0,1,"pl-s"],[1,2,"pl-v"],[3,5,"pl-s"],[31,33,"pl-s"],[35,36,"pl-s"],[36,70,"pl-c1"],[70,71,"pl-s"]],[[3,4,"pl-v"]],[[3,4,"pl-v"]],[],[[0,1,"pl-s"],[1,2,"pl-v"],[3,5,"pl-s"],[25,27,"pl-s"],[29,30,"pl-s"],[30,57,"pl-c1"],[57,58,"pl-s"]],[[3,4,"pl-v"],[5,6,"pl-s"],[6,17,"pl-c1"],[17,18,"pl-s"]],[[3,4,"pl-v"],[5,6,"pl-s"],[6,18,"pl-c1"],[18,19,"pl-s"]],[[3,4,"pl-v"],[5,6,"pl-s"],[6,21,"pl-c1"],[21,22,"pl-s"]],[],[[0,1,"pl-s"],[1,2,"pl-v"],[3,5,"pl-s"],[25,27,"pl-s"],[29,30,"pl-s"],[30,53,"pl-c1"],[53,54,"pl-s"]],[[3,4,"pl-v"]],[[3,4,"pl-v"]],[],[[0,19,"pl-mh"],[3,19,"pl-en"]],[],[[0,52,"pl-mh"],[4,52,"pl-en"]],[],[[0,2,"pl-s"],[10,12,"pl-s"]],[],[[0,2,"pl-s"],[16,18,"pl-s"]],[[0,1,"pl-v"],[21,22,"pl-s"],[22,29,"pl-c1"],[29,30,"pl-s"],[32,33,"pl-s"],[33,39,"pl-c1"],[39,40,"pl-s"],[42,43,"pl-s"],[43,48,"pl-c1"],[48,49,"pl-s"],[51,52,"pl-s"],[52,60,"pl-c1"],[60,61,"pl-s"],[63,64,"pl-s"],[64,73,"pl-c1"],[73,74,"pl-s"],[76,77,"pl-s"],[77,86,"pl-c1"],[86,87,"pl-s"],[89,90,"pl-s"],[90,94,"pl-c1"],[94,95,"pl-s"]],[[0,1,"pl-v"],[5,6,"pl-s"],[6,15,"pl-c1"],[15,16,"pl-s"]],[],[[0,2,"pl-s"],[11,13,"pl-s"]],[[0,1,"pl-v"],[6,7,"pl-s"],[7,21,"pl-c1"],[21,22,"pl-s"],[35,36,"pl-s"],[36,60,"pl-c1"],[60,61,"pl-s"]],[[0,1,"pl-v"],[15,16,"pl-s"],[16,83,"pl-c1"],[83,84,"pl-s"]],[[0,1,"pl-v"],[12,13,"pl-s"],[13,38,"pl-c1"],[38,39,"pl-s"]],[[0,1,"pl-v"]],[],[[0,2,"pl-s"],[23,25,"pl-s"]],[[0,3,"pl-s"],[3,6,"pl-en"],[6,6,"pl-c1"]],[[0,46,"pl-c1"]],[[0,14,"pl-c1"]],[[0,7,"pl-c1"]],[[0,24,"pl-c1"]],[[0,39,"pl-c1"]],[[0,49,"pl-c1"]],[[0,29,"pl-c1"]],[[0,1,"pl-c1"]],[[0,0,"pl-c1"],[0,3,"pl-s"]],[],[[0,59,"pl-mh"],[4,59,"pl-en"]],[],[[0,2,"pl-s"],[10,12,"pl-s"]],[],[[0,2,"pl-s"],[16,18,"pl-s"]],[[0,1,"pl-v"],[30,31,"pl-s"],[31,46,"pl-c1"],[46,47,"pl-s"],[51,52,"pl-s"],[52,87,"pl-c1"],[87,88,"pl-s"]],[[0,1,"pl-v"],[19,20,"pl-s"],[20,60,"pl-c1"],[60,61,"pl-s"]],[[0,1,"pl-v"],[18,19,"pl-s"],[19,32,"pl-c1"],[32,33,"pl-s"]],[],[[0,2,"pl-s"],[11,13,"pl-s"]],[[0,1,"pl-v"],[6,7,"pl-s"],[7,25,"pl-c1"],[25,26,"pl-s"],[39,40,"pl-s"],[40,64,"pl-c1"],[64,65,"pl-s"]],[[0,1,"pl-v"]],[[0,1,"pl-v"]],[],[[0,2,"pl-s"],[23,25,"pl-s"]],[[0,3,"pl-s"],[3,6,"pl-en"],[6,6,"pl-c1"]],[[0,52,"pl-c1"]],[[0,1,"pl-c1"]],[[0,28,"pl-c1"]],[[0,23,"pl-c1"]],[[0,20,"pl-c1"]],[[0,43,"pl-c1"]],[[0,16,"pl-c1"]],[[0,1,"pl-c1"]],[[0,0,"pl-c1"],[0,3,"pl-s"]],[],[[0,66,"pl-mh"],[4,66,"pl-en"]],[],[[0,2,"pl-s"],[10,12,"pl-s"]],[],[[0,2,"pl-s"],[16,18,"pl-s"]],[[0,1,"pl-v"],[25,26,"pl-s"],[26,40,"pl-c1"],[40,41,"pl-s"],[45,46,"pl-s"],[46,80,"pl-c1"],[80,81,"pl-s"]],[[0,1,"pl-v"],[20,21,"pl-s"],[21,71,"pl-c1"],[71,72,"pl-s"]],[[0,1,"pl-v"],[13,14,"pl-s"],[14,22,"pl-c1"],[22,23,"pl-s"]],[],[[0,2,"pl-s"],[11,13,"pl-s"]],[[0,1,"pl-v"],[6,7,"pl-s"],[7,23,"pl-c1"],[23,24,"pl-s"],[37,38,"pl-s"],[38,62,"pl-c1"],[62,63,"pl-s"]],[[0,1,"pl-v"]],[[0,1,"pl-v"],[33,34,"pl-s"],[34,62,"pl-c1"],[62,63,"pl-s"]],[[0,1,"pl-v"],[29,30,"pl-s"],[30,59,"pl-c1"],[59,60,"pl-s"]],[[0,1,"pl-v"],[13,14,"pl-s"],[14,42,"pl-c1"],[42,43,"pl-s"]],[],[[0,2,"pl-s"],[23,25,"pl-s"]],[[0,3,"pl-s"],[3,6,"pl-en"],[6,6,"pl-c1"]],[[0,42,"pl-c1"]],[[0,1,"pl-c1"]],[[0,45,"pl-c1"]],[[0,40,"pl-c1"]],[[0,20,"pl-c1"]],[[0,23,"pl-c1"]],[[0,31,"pl-c1"]],[[0,1,"pl-c1"]],[[0,0,"pl-c1"]],[[0,68,"pl-c1"]],[[0,1,"pl-c1"]],[[0,17,"pl-c1"]],[[0,47,"pl-c1"]],[[0,1,"pl-c1"]],[[0,0,"pl-c1"],[0,3,"pl-s"]],[],[[0,62,"pl-mh"],[4,62,"pl-en"]],[],[[0,2,"pl-s"],[10,12,"pl-s"]],[],[[0,2,"pl-s"],[16,18,"pl-s"]],[[0,1,"pl-v"],[17,18,"pl-s"],[18,31,"pl-c1"],[31,32,"pl-s"],[43,44,"pl-s"],[44,70,"pl-c1"],[70,71,"pl-s"]],[[0,1,"pl-v"]],[],[[0,2,"pl-s"],[11,13,"pl-s"]],[[0,1,"pl-v"],[20,21,"pl-s"],[21,35,"pl-c1"],[35,36,"pl-s"],[38,39,"pl-s"],[39,59,"pl-c1"],[59,60,"pl-s"],[62,63,"pl-s"],[63,78,"pl-c1"],[78,79,"pl-s"],[81,82,"pl-s"],[82,101,"pl-c1"],[101,102,"pl-s"]],[[0,1,"pl-v"],[18,19,"pl-s"],[19,42,"pl-c1"],[42,43,"pl-s"],[51,52,"pl-s"],[52,82,"pl-c1"],[82,83,"pl-s"]],[[0,1,"pl-v"],[15,16,"pl-s"],[16,40,"pl-c1"],[40,41,"pl-s"]],[],[[0,2,"pl-s"],[23,25,"pl-s"]],[[0,3,"pl-s"],[3,6,"pl-en"],[6,6,"pl-c1"]],[[0,23,"pl-c1"]],[[0,1,"pl-c1"]],[[0,27,"pl-c1"]],[[0,43,"pl-c1"]],[[0,24,"pl-c1"]],[[0,28,"pl-c1"]],[[0,21,"pl-c1"]],[[0,1,"pl-c1"]],[[0,0,"pl-c1"],[0,3,"pl-s"]],[],[[0,52,"pl-mh"],[4,52,"pl-en"]],[],[[0,2,"pl-s"],[10,12,"pl-s"],[83,84,"pl-s"],[84,96,"pl-c1"],[96,97,"pl-s"]],[],[[0,2,"pl-s"],[16,18,"pl-s"]],[[0,1,"pl-v"],[13,14,"pl-s"],[14,24,"pl-c1"],[24,25,"pl-s"],[43,44,"pl-s"],[44,69,"pl-c1"],[69,70,"pl-s"]],[[0,1,"pl-v"],[11,12,"pl-s"],[12,24,"pl-c1"],[24,25,"pl-s"]],[[0,1,"pl-v"]],[],[[0,2,"pl-s"],[11,13,"pl-s"]],[[0,1,"pl-v"],[6,7,"pl-s"],[7,22,"pl-c1"],[22,23,"pl-s"],[32,33,"pl-s"],[33,64,"pl-c1"],[64,65,"pl-s"]],[[0,1,"pl-v"],[18,19,"pl-s"],[19,29,"pl-c1"],[29,30,"pl-s"]],[[0,1,"pl-v"]],[[0,1,"pl-v"]],[],[[0,2,"pl-s"],[23,25,"pl-s"]],[[0,3,"pl-s"],[3,6,"pl-en"],[6,6,"pl-c1"]],[[0,17,"pl-c1"]],[[0,1,"pl-c1"]],[[0,28,"pl-c1"]],[[0,16,"pl-c1"]],[[0,35,"pl-c1"]],[[0,45,"pl-c1"]],[[0,42,"pl-c1"]],[[0,3,"pl-c1"]],[[0,1,"pl-c1"]],[[0,0,"pl-c1"],[0,3,"pl-s"]],[],[[0,57,"pl-mh"],[4,57,"pl-en"]],[],[[0,2,"pl-s"],[10,12,"pl-s"]],[],[[0,2,"pl-s"],[16,18,"pl-s"]],[[0,1,"pl-v"]],[[0,1,"pl-v"]],[],[[0,2,"pl-s"],[11,13,"pl-s"]],[[0,1,"pl-v"],[8,9,"pl-s"],[9,24,"pl-c1"],[24,25,"pl-s"]],[[0,1,"pl-v"]],[[0,1,"pl-v"]],[],[[0,2,"pl-s"],[23,25,"pl-s"]],[[0,3,"pl-s"],[3,6,"pl-en"],[6,6,"pl-c1"]],[[0,24,"pl-c1"]],[[0,10,"pl-c1"]],[[0,1,"pl-c1"]],[[0,20,"pl-c1"]],[[0,18,"pl-c1"]],[[0,15,"pl-c1"]],[[0,43,"pl-c1"]],[[0,32,"pl-c1"]],[[0,27,"pl-c1"]],[[0,3,"pl-c1"]],[[0,1,"pl-c1"]],[[0,0,"pl-c1"],[0,3,"pl-s"]],[],[[0,56,"pl-mh"],[4,56,"pl-en"]],[],[[0,2,"pl-s"],[10,12,"pl-s"]],[],[[0,2,"pl-s"],[16,18,"pl-s"]],[[0,1,"pl-v"],[35,36,"pl-s"],[36,54,"pl-c1"],[54,55,"pl-s"]],[[0,1,"pl-v"]],[],[[0,2,"pl-s"],[9,11,"pl-s"],[49,50,"pl-s"],[50,68,"pl-c1"],[68,69,"pl-s"]],[],[[0,2,"pl-s"],[23,25,"pl-s"]],[[0,1,"pl-v"],[34,35,"pl-s"],[35,58,"pl-c1"],[58,59,"pl-s"]],[[0,1,"pl-v"]],[],[[0,25,"pl-mh"],[3,25,"pl-en"]],[],[[0,37,"pl-mh"],[4,37,"pl-en"]],[],[],[],[[0,1,"pl-s"],[1,2,"pl-v"],[3,5,"pl-s"],[20,22,"pl-s"],[24,25,"pl-s"],[25,41,"pl-c1"],[41,42,"pl-s"]],[[3,4,"pl-v"]],[[3,4,"pl-v"]],[[3,4,"pl-v"]],[[3,4,"pl-v"],[11,12,"pl-s"],[12,36,"pl-c1"],[36,37,"pl-s"]],[],[[0,1,"pl-s"],[1,2,"pl-v"],[3,5,"pl-s"],[22,24,"pl-s"],[26,27,"pl-s"],[27,41,"pl-c1"],[41,42,"pl-s"]],[[3,4,"pl-v"]],[[3,4,"pl-v"]],[[3,4,"pl-v"],[26,27,"pl-s"],[27,48,"pl-c1"],[48,49,"pl-s"]],[[3,4,"pl-v"],[11,12,"pl-s"],[12,36,"pl-c1"],[36,37,"pl-s"]],[],[[0,1,"pl-s"],[1,2,"pl-v"],[3,5,"pl-s"],[22,24,"pl-s"],[26,27,"pl-s"],[27,45,"pl-c1"],[45,46,"pl-s"]],[[3,4,"pl-v"]],[[3,4,"pl-v"]],[[3,4,"pl-v"]],[[3,4,"pl-v"],[11,12,"pl-s"],[12,36,"pl-c1"],[36,37,"pl-s"]],[],[[0,37,"pl-mh"],[4,37,"pl-en"]],[],[],[],[[0,1,"pl-s"],[1,2,"pl-v"],[3,5,"pl-s"],[24,26,"pl-s"]],[[3,4,"pl-v"]],[[3,4,"pl-v"]],[[3,4,"pl-v"]],[[3,4,"pl-v"],[12,13,"pl-s"],[13,37,"pl-c1"],[37,38,"pl-s"],[40,41,"pl-s"],[41,51,"pl-c1"],[51,52,"pl-s"]],[],[[0,31,"pl-mh"],[4,31,"pl-en"]],[],[[0,1,"pl-s"],[1,2,"pl-v"],[3,5,"pl-s"],[22,24,"pl-s"]],[[3,4,"pl-v"]],[[3,4,"pl-v"]],[[3,4,"pl-v"]],[[3,4,"pl-v"],[11,12,"pl-s"],[12,35,"pl-c1"],[35,36,"pl-s"]],[],[[0,30,"pl-mh"],[4,30,"pl-en"]],[],[[0,1,"pl-s"],[1,2,"pl-v"],[3,5,"pl-s"],[18,20,"pl-s"]],[[3,4,"pl-v"]],[[3,4,"pl-v"]],[[3,4,"pl-v"]],[[3,4,"pl-v"],[11,12,"pl-s"],[12,43,"pl-c1"],[43,44,"pl-s"]],[],[[0,32,"pl-mh"],[4,32,"pl-en"]],[],[[0,1,"pl-s"],[1,2,"pl-v"],[3,5,"pl-s"],[21,23,"pl-s"]],[[3,4,"pl-v"]],[[3,4,"pl-v"]],[[3,4,"pl-v"],[11,12,"pl-s"],[12,35,"pl-c1"],[35,36,"pl-s"]],[],[[0,20,"pl-mh"],[3,20,"pl-en"]],[],[[0,31,"pl-mh"],[4,31,"pl-en"]],[],[[0,3,"pl-s"],[3,6,"pl-en"],[6,6,"pl-c1"]],[[0,51,"pl-c1"]],[[0,0,"pl-c1"]],[[0,45,"pl-c1"]],[[0,16,"pl-c1"]],[[0,30,"pl-c1"]],[[0,29,"pl-c1"]],[[0,0,"pl-c1"]],[[0,8,"pl-c1"]],[[0,1,"pl-c1"]],[[0,45,"pl-c1"]],[[0,40,"pl-c1"]],[[0,20,"pl-c1"]],[[0,23,"pl-c1"]],[[0,31,"pl-c1"]],[[0,1,"pl-c1"]],[[0,0,"pl-c1"]],[[0,9,"pl-c1"]],[[0,1,"pl-c1"]],[[0,17,"pl-c1"]],[[0,48,"pl-c1"]],[[0,31,"pl-c1"]],[[0,1,"pl-c1"]],[[0,0,"pl-c1"]],[[0,27,"pl-c1"]],[[0,14,"pl-c1"]],[[0,30,"pl-c1"]],[[0,29,"pl-c1"]],[[0,0,"pl-c1"]],[[0,8,"pl-c1"]],[[0,1,"pl-c1"]],[[0,24,"pl-c1"]],[[0,39,"pl-c1"]],[[0,44,"pl-c1"]],[[0,29,"pl-c1"]],[[0,1,"pl-c1"]],[[0,0,"pl-c1"]],[[0,9,"pl-c1"]],[[0,1,"pl-c1"]],[[0,17,"pl-c1"]],[[0,23,"pl-c1"]],[[0,1,"pl-c1"]],[[0,0,"pl-c1"]],[[0,23,"pl-c1"]],[[0,18,"pl-c1"]],[[0,30,"pl-c1"]],[[0,29,"pl-c1"]],[[0,0,"pl-c1"]],[[0,8,"pl-c1"]],[[0,1,"pl-c1"]],[[0,28,"pl-c1"]],[[0,23,"pl-c1"]],[[0,20,"pl-c1"]],[[0,42,"pl-c1"]],[[0,15,"pl-c1"]],[[0,41,"pl-c1"]],[[0,3,"pl-c1"]],[[0,1,"pl-c1"]],[[0,0,"pl-c1"]],[[0,9,"pl-c1"]],[[0,1,"pl-c1"]],[[0,22,"pl-c1"]],[[0,1,"pl-c1"]],[[0,0,"pl-c1"],[0,3,"pl-s"]],[],[[0,33,"pl-mh"],[4,33,"pl-en"]],[],[[0,3,"pl-s"],[3,6,"pl-en"],[6,6,"pl-c1"]],[[0,58,"pl-c1"]],[[0,51,"pl-c1"]],[[0,0,"pl-c1"]],[[0,21,"pl-c1"]],[[0,33,"pl-c1"]],[[0,32,"pl-c1"]],[[0,17,"pl-c1"]],[[0,23,"pl-c1"]],[[0,25,"pl-c1"]],[[0,24,"pl-c1"]],[[0,9,"pl-c1"]],[[0,46,"pl-c1"]],[[0,48,"pl-c1"]],[[0,1,"pl-c1"]],[[0,0,"pl-c1"],[0,3,"pl-s"]],[],[[0,21,"pl-mh"],[4,21,"pl-en"]],[],[[0,3,"pl-s"],[3,3,"pl-c1"]],[[0,22,"pl-c1"]],[[0,55,"pl-c1"]],[[0,0,"pl-c1"]],[[0,41,"pl-c1"]],[[0,41,"pl-c1"]],[[0,35,"pl-c1"]],[[0,29,"pl-c1"]],[[0,57,"pl-c1"]],[[0,0,"pl-c1"]],[[0,11,"pl-c1"]],[[0,23,"pl-c1"]],[[0,63,"pl-c1"]],[[0,33,"pl-c1"]],[[0,0,"pl-c1"]],[[0,17,"pl-c1"]],[[0,25,"pl-c1"]],[[0,33,"pl-c1"]],[[0,33,"pl-c1"]],[[0,0,"pl-c1"]],[[0,11,"pl-c1"]],[[0,17,"pl-c1"]],[[0,18,"pl-c1"]],[[0,36,"pl-c1"]],[[0,39,"pl-c1"]],[[0,0,"pl-c1"]],[[0,9,"pl-c1"]],[[0,34,"pl-c1"]],[[0,36,"pl-c1"]],[[0,34,"pl-c1"]],[[0,31,"pl-c1"]],[[0,0,"pl-c1"]],[[0,10,"pl-c1"]],[[0,52,"pl-c1"]],[[0,0,"pl-c1"],[0,3,"pl-s"]],[],[[0,24,"pl-mh"],[3,24,"pl-en"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,33,"pl-ii"]],[],[[2,14,"pl-ent"]],[[4,9,"pl-ent"],[11,35,"pl-s"],[11,12,"pl-pds"],[34,35,"pl-pds"]],[[4,15,"pl-ent"],[17,32,"pl-s"],[17,18,"pl-pds"],[31,32,"pl-pds"]],[[4,10,"pl-ent"],[13,27,"pl-s"],[13,14,"pl-pds"],[26,27,"pl-pds"],[29,38,"pl-s"],[29,30,"pl-pds"],[37,38,"pl-pds"]],[[4,20,"pl-ent"],[22,23,"pl-c1"]],[[4,19,"pl-ent"],[21,25,"pl-c1"]],[],[[2,11,"pl-ent"]],[[4,28,"pl-ent"],[30,34,"pl-c1"]],[[4,30,"pl-ent"],[32,36,"pl-c1"]],[[4,21,"pl-ent"],[23,27,"pl-c1"]],[],[],[[0,3,"pl-s"]],[],[[0,17,"pl-mh"],[3,17,"pl-en"]],[],[[0,1,"pl-ml"],[10,11,"pl-ml"],[17,18,"pl-ml"],[27,28,"pl-ml"]],[[0,1,"pl-ml"],[10,11,"pl-ml"],[17,18,"pl-ml"],[27,28,"pl-ml"]],[[0,1,"pl-ml"],[11,12,"pl-ml"],[13,14,"pl-s"],[14,29,"pl-c1"],[29,30,"pl-s"],[31,32,"pl-ml"],[92,93,"pl-ml"]],[[0,1,"pl-ml"],[11,12,"pl-ml"],[13,14,"pl-s"],[14,28,"pl-c1"],[28,29,"pl-s"],[30,31,"pl-ml"],[61,62,"pl-ml"]],[[0,1,"pl-ml"],[11,12,"pl-ml"],[13,14,"pl-s"],[14,28,"pl-c1"],[28,29,"pl-s"],[30,31,"pl-ml"],[67,68,"pl-ml"]],[[0,1,"pl-ml"],[11,12,"pl-ml"],[13,14,"pl-s"],[14,36,"pl-c1"],[36,37,"pl-s"],[38,39,"pl-ml"],[69,70,"pl-ml"]],[[0,1,"pl-ml"],[11,12,"pl-ml"],[13,14,"pl-s"],[14,32,"pl-c1"],[32,33,"pl-s"],[34,35,"pl-ml"],[59,60,"pl-ml"]],[[0,1,"pl-ml"],[13,14,"pl-ml"],[15,16,"pl-s"],[16,27,"pl-c1"],[27,28,"pl-s"],[29,30,"pl-ml"],[82,83,"pl-ml"]],[[0,1,"pl-ml"],[14,15,"pl-ml"],[16,17,"pl-s"],[17,28,"pl-c1"],[28,29,"pl-s"],[30,31,"pl-ml"],[79,80,"pl-ml"]],[],[[0,13,"pl-mh"],[3,13,"pl-en"]],[],[[0,12,"pl-mh"],[4,12,"pl-en"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,18,"pl-c1"],[18,19,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,21,"pl-c1"],[21,22,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,18,"pl-c1"],[18,19,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,32,"pl-c1"],[32,33,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,24,"pl-c1"],[24,25,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,28,"pl-c1"],[28,29,"pl-s"]],[],[[0,14,"pl-mh"],[4,14,"pl-en"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,17,"pl-c1"],[17,18,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,19,"pl-c1"],[19,20,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,20,"pl-c1"],[20,21,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,14,"pl-c1"],[14,15,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,16,"pl-c1"],[16,17,"pl-s"]],[],[[0,15,"pl-mh"],[4,15,"pl-en"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,14,"pl-c1"],[14,15,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,16,"pl-c1"],[16,17,"pl-s"]],[[0,1,"pl-v"],[2,3,"pl-s"],[3,17,"pl-c1"],[17,18,"pl-s"]],[],[[0,18,"pl-mh"],[3,18,"pl-en"]],[],[[0,1,"pl-ml"],[7,8,"pl-ml"],[16,17,"pl-ml"],[26,27,"pl-ml"]],[[0,1,"pl-ml"],[7,8,"pl-ml"],[16,17,"pl-ml"],[26,27,"pl-ml"]],[[0,1,"pl-ml"],[13,14,"pl-ml"],[15,24,"pl-s"],[16,24,"pl-corl"],[25,26,"pl-ml"],[78,79,"pl-ml"]],[],[[0,3,"pl-ms"]],[],[[0,1,"pl-s"],[125,126,"pl-s"]]],"colorizedLines":null}},"title":"nullclaw/docs/integration-analysis.md at main · nullclaw/nullclaw","appPayload":{},"meta":{"title":"nullclaw/docs/integration-analysis.md at main · nullclaw/nullclaw"}}</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="/nullclaw/nullclaw" 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="/nullclaw/nullclaw/tree/main" data-discover="true">nullclaw</a></li><li class="Breadcrumb-module__listItem__Ib0x_"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__lg__Rjz0A" aria-hidden="true">/</span><a class="Breadcrumb-module__directoryLink__kQy_t prc-Link-Link-9ZwDx" data-component="Link" href="/nullclaw/nullclaw/tree/main/docs" data-discover="true">docs</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">integration-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="/nullclaw/nullclaw/commits/main/docs/integration-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="/nullclaw/nullclaw/commits/main/docs/integration-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="14.6 KB" style="--truncate-max-width:100%"><span>489 lines (387 loc) · 14.6 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="/nullclaw/nullclaw/tree/main" data-discover="true">nullclaw</a></li><li class="Breadcrumb-module__listItem__Ib0x_"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__md__Wb1Gs" aria-hidden="true">/</span><a class="Breadcrumb-module__directoryLink__kQy_t prc-Link-Link-9ZwDx" data-component="Link" href="/nullclaw/nullclaw/tree/main/docs" data-discover="true">docs</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">integration-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="14.6 KB" style="--truncate-max-width:100%"><span>489 lines (387 loc) · 14.6 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/nullclaw/nullclaw/raw/refs/heads/main/docs/integration-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">Integration Analysis: nullclaw + nullboiler + nulltickets</h1><a id="user-content-integration-analysis-nullclaw--nullboiler--nulltickets" class="anchor" aria-label="Permalink: Integration Analysis: nullclaw + nullboiler + nulltickets" href="#integration-analysis-nullclaw--nullboiler--nulltickets"><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="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Executive Summary</h2><a id="user-content-executive-summary" class="anchor" aria-label="Permalink: Executive Summary" href="#executive-summary"><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">This document analyzes the integration gaps between three nullclaw ecosystem projects to enable end-to-end multi-agent workflows with Telegram topic routing.</p>
<p dir="auto"><strong>Target Scenario:</strong></p>
<blockquote>
<p dir="auto">User sends message in Telegram General topic → Orchestrator agent decides to delegate coding task → Coder agent executes → Result appears in the Coder topic in Telegram</p>
</blockquote>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Architecture Overview</h2><a id="user-content-architecture-overview" class="anchor" aria-label="Permalink: Architecture Overview" href="#architecture-overview"><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="┌─────────────────┐     ┌──────────────────┐     ┌─────────────────┐
│   nulltickets   │────▶│   nullboiler     │────▶│    nullclaw     │
│  (Task Tracker) │     │ (DAG Orchestrator)│     │  (AI Runtime)   │
└─────────────────┘     └──────────────────┘     └─────────────────┘
         │                       │                       │
         ▼                       ▼                       ▼
   Pipeline FSM             Workflow DAG           Telegram Topics
   Lease-based              Step dispatch          Agent routing
   Role routing             Worker selection       Tool execution"><pre class="notranslate"><code>┌─────────────────┐     ┌──────────────────┐     ┌─────────────────┐
│   nulltickets   │────▶│   nullboiler     │────▶│    nullclaw     │
│  (Task Tracker) │     │ (DAG Orchestrator)│     │  (AI Runtime)   │
└─────────────────┘     └──────────────────┘     └─────────────────┘
         │                       │                       │
         ▼                       ▼                       ▼
   Pipeline FSM             Workflow DAG           Telegram Topics
   Lease-based              Step dispatch          Agent routing
   Role routing             Worker selection       Tool execution
</code></pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Project Roles</h3><a id="user-content-project-roles" class="anchor" aria-label="Permalink: Project Roles" href="#project-roles"><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>Component</th>
<th>Responsibility</th>
<th>Key Files</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>nulltickets</strong></td>
<td>Durable task state, FSM transitions, lease coordination</td>
<td><code>src/api.zig</code>, <code>src/store.zig</code>, <code>src/domain.zig</code></td>
</tr>
<tr>
<td><strong>nullboiler</strong></td>
<td>DAG scheduling, worker dispatch, step orchestration</td>
<td><code>src/engine.zig</code>, <code>src/dispatch.zig</code>, <code>src/callbacks.zig</code></td>
</tr>
<tr>
<td><strong>nullclaw</strong></td>
<td>AI agent runtime, tool execution, Telegram integration</td>
<td><code>src/agent/root.zig</code>, <code>src/gateway.zig</code>, <code>src/session.zig</code></td>
</tr>
</tbody>
</table></markdown-accessiblity-table>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Current Capabilities</h2><a id="user-content-current-capabilities" class="anchor" aria-label="Permalink: Current Capabilities" href="#current-capabilities"><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="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">✅ What Already Works</h3><a id="user-content--what-already-works" class="anchor" aria-label="Permalink: ✅ What Already Works" href="#-what-already-works"><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>
<ol dir="auto">
<li>
<p dir="auto"><strong>Telegram Topic Delivery</strong> (<code>nullclaw/src/channels/telegram.zig:146-156</code>)</p>
<ul dir="auto">
<li>Supports <code>chatid#topic:threadid</code> format for forum topics</li>
<li><code>MessageTool</code> can send to any channel/topic combination</li>
</ul>
</li>
<li>
<p dir="auto"><strong>Agent Routing per Topic</strong> (<code>nullclaw/src/agent_bindings_config.zig</code>)</p>
<ul dir="auto">
<li>7-tier binding system: peer → parent_peer → guild_roles → guild → team → account → default</li>
<li><code>/bind</code> command for runtime topic-to-agent binding</li>
</ul>
</li>
<li>
<p dir="auto"><strong>nullboiler Callback System</strong> (<code>nullboiler/src/callbacks.zig:21-114</code>)</p>
<ul dir="auto">
<li>Webhook callbacks on events: <code>step.completed</code>, <code>step.failed</code>, <code>run.completed</code>, <code>run.failed</code></li>
<li>Supports custom headers and HMAC signing</li>
</ul>
</li>
<li>
<p dir="auto"><strong>nullboiler Worker Dispatch</strong> (<code>nullboiler/src/dispatch.zig:89-199</code>)</p>
<ul dir="auto">
<li>5 protocols: webhook, api_chat, openai_chat, mqtt, redis_stream</li>
<li>Tag-based worker selection with least-loaded balancing</li>
</ul>
</li>
<li>
<p dir="auto"><strong>nullclaw Tool System</strong> (<code>nullclaw/src/tools/root.zig</code>)</p>
<ul dir="auto">
<li><code>MessageTool</code> — send to any channel/topic internally</li>
<li><code>DelegateTool</code> — synchronous sub-agent delegation</li>
<li><code>HttpRequestTool</code> — arbitrary HTTP calls</li>
</ul>
</li>
<li>
<p dir="auto"><strong>Agent Profile System</strong> (<code>nullclaw/src/config.zig</code>)</p>
<ul dir="auto">
<li>Named agents with different providers, models, system prompts</li>
<li>Session-scoped agent instances</li>
</ul>
</li>
</ol>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Integration Gaps</h2><a id="user-content-integration-gaps" class="anchor" aria-label="Permalink: Integration Gaps" href="#integration-gaps"><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="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Gap 1: External Message Send API (HIGH PRIORITY)</h3><a id="user-content-gap-1-external-message-send-api-high-priority" class="anchor" aria-label="Permalink: Gap 1: External Message Send API (HIGH PRIORITY)" href="#gap-1-external-message-send-api-high-priority"><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"><strong>Problem:</strong> nullclaw's gateway is inbound-only. No endpoint exists for external services (like nullboiler) to trigger outbound messages to specific Telegram topics.</p>
<p dir="auto"><strong>Current State:</strong></p>
<ul dir="auto">
<li>Gateway endpoints: <code>/health</code>, <code>/ready</code>, <code>/pair</code>, <code>/webhook</code>, <code>/telegram</code>, <code>/whatsapp</code>, <code>/a2a</code></li>
<li>No <code>/api/send</code> or similar endpoint</li>
</ul>
<p dir="auto"><strong>Required:</strong></p>
<ul dir="auto">
<li>New <code>POST /api/send</code> endpoint in <code>nullclaw/src/gateway.zig</code></li>
<li>Accept JSON: <code>{channel: "telegram", chat_id: "-100123#topic:456", content: "..."}</code></li>
<li>Hook into <code>bus.Bus.publishOutbound()</code> for delivery</li>
<li>Authentication via existing token/pairing system</li>
</ul>
<p dir="auto"><strong>Implementation Notes:</strong></p>
<div class="highlight highlight-source-zig notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// Potential endpoint structure in gateway.zig
POST /api/send
Body: {
  &quot;channel&quot;: &quot;telegram&quot;,
  &quot;chat_id&quot;: &quot;-1001234567890#topic:42&quot;,
  &quot;content&quot;: &quot;Coder agent completed the task...&quot;,
  &quot;reply_to_message_id&quot;: null
}"><pre><span class="pl-c">// Potential endpoint structure in gateway.zig</span>
<span class="pl-v">POST</span> <span class="pl-k">/</span><span class="pl-v">api</span><span class="pl-k">/</span><span class="pl-v">send</span>
<span class="pl-en">Body</span>: {
  <span class="pl-s">"channel"</span>: <span class="pl-s">"telegram"</span>,
  <span class="pl-s">"chat_id"</span>: <span class="pl-s">"-1001234567890#topic:42"</span>,
  <span class="pl-s">"content"</span>: <span class="pl-s">"Coder agent completed the task..."</span>,
  <span class="pl-s">"reply_to_message_id"</span>: <span class="pl-c1">null</span>
}</pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Gap 2: Callback Receiver for nullboiler (HIGH PRIORITY)</h3><a id="user-content-gap-2-callback-receiver-for-nullboiler-high-priority" class="anchor" aria-label="Permalink: Gap 2: Callback Receiver for nullboiler (HIGH PRIORITY)" href="#gap-2-callback-receiver-for-nullboiler-high-priority"><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"><strong>Problem:</strong> nullboiler can fire callbacks when steps complete, but nullclaw has no endpoint to receive them.</p>
<p dir="auto"><strong>Current State:</strong></p>
<ul dir="auto">
<li>nullboiler fires callbacks: <code>fireCallbacks()</code> in <code>nullboiler/src/callbacks.zig:21-114</code></li>
<li>Callback format: <code>{event, run_id, step_id, output, status}</code></li>
<li>nullclaw has no <code>/api/callback</code> endpoint</li>
</ul>
<p dir="auto"><strong>Required:</strong></p>
<ul dir="auto">
<li>New <code>POST /api/callback</code> endpoint in <code>nullclaw/src/gateway.zig</code></li>
<li>Parse nullboiler callback format</li>
<li>Route results to appropriate Telegram topic via outbound bus</li>
</ul>
<p dir="auto"><strong>Implementation Notes:</strong></p>
<div class="highlight highlight-source-zig notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// Callback format from nullboiler/src/callbacks.zig
{
  &quot;event&quot;: &quot;step.completed&quot;,
  &quot;run_id&quot;: &quot;run-uuid&quot;,
  &quot;step_id&quot;: &quot;code&quot;,
  &quot;output&quot;: &quot;The generated bash script...&quot;,
  &quot;status&quot;: &quot;ok&quot;
}"><pre><span class="pl-c">// Callback format from nullboiler/src/callbacks.zig</span>
{
  <span class="pl-s">"event"</span>: <span class="pl-s">"step.completed"</span>,
  <span class="pl-s">"run_id"</span>: <span class="pl-s">"run-uuid"</span>,
  <span class="pl-s">"step_id"</span>: <span class="pl-s">"code"</span>,
  <span class="pl-s">"output"</span>: <span class="pl-s">"The generated bash script..."</span>,
  <span class="pl-s">"status"</span>: <span class="pl-s">"ok"</span>
}</pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Gap 3: Worker Endpoint for nullboiler Dispatch (HIGH PRIORITY)</h3><a id="user-content-gap-3-worker-endpoint-for-nullboiler-dispatch-high-priority" class="anchor" aria-label="Permalink: Gap 3: Worker Endpoint for nullboiler Dispatch (HIGH PRIORITY)" href="#gap-3-worker-endpoint-for-nullboiler-dispatch-high-priority"><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"><strong>Problem:</strong> nullboiler dispatches steps to workers via HTTP POST, but nullclaw has no endpoint that accepts nullboiler's step format.</p>
<p dir="auto"><strong>Current State:</strong></p>
<ul dir="auto">
<li>nullboiler dispatches: <code>dispatchStep()</code> in <code>nullboiler/src/dispatch.zig:89-199</code></li>
<li>Dispatch payload: <code>{prompt, context, step_id, run_id, correlation_id}</code></li>
<li>nullclaw's <code>/webhook</code> is designed for Telegram, not generic worker tasks</li>
</ul>
<p dir="auto"><strong>Required:</strong></p>
<ul dir="auto">
<li>New <code>POST /api/worker</code> endpoint in <code>nullclaw/src/gateway.zig</code></li>
<li>Accept nullboiler step dispatch format</li>
<li>Route to appropriate agent via <code>agent_routing.resolveRoute()</code></li>
<li>Return response in format: <code>{status:"ok", response:"..."}</code></li>
<li>Handle via <code>session_mgr.processMessage()</code> for agent execution</li>
</ul>
<p dir="auto"><strong>Implementation Notes:</strong></p>
<div class="highlight highlight-source-zig notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// Worker dispatch payload from nullboiler
{
  &quot;prompt&quot;: &quot;Generate a bash script that...&quot;,
  &quot;context&quot;: {&quot;previous_output&quot;: &quot;...&quot;},
  &quot;step_id&quot;: &quot;code&quot;,
  &quot;run_id&quot;: &quot;run-uuid&quot;,
  &quot;correlation_id&quot;: &quot;corr-uuid&quot;
}

// Expected response format (nullboiler/src/worker_response.zig:102)
{
  &quot;status&quot;: &quot;ok&quot;,
  &quot;response&quot;: &quot;#!/bin/bash\necho 'Hello World'&quot;
}"><pre><span class="pl-c">// Worker dispatch payload from nullboiler</span>
{
  <span class="pl-s">"prompt"</span>: <span class="pl-s">"Generate a bash script that..."</span>,
  <span class="pl-s">"context"</span>: {<span class="pl-s">"previous_output"</span>: <span class="pl-s">"..."</span>},
  <span class="pl-s">"step_id"</span>: <span class="pl-s">"code"</span>,
  <span class="pl-s">"run_id"</span>: <span class="pl-s">"run-uuid"</span>,
  <span class="pl-s">"correlation_id"</span>: <span class="pl-s">"corr-uuid"</span>
}

<span class="pl-c">// Expected response format (nullboiler/src/worker_response.zig:102)</span>
{
  <span class="pl-s">"status"</span>: <span class="pl-s">"ok"</span>,
  <span class="pl-s">"response"</span>: <span class="pl-s">"#!/bin/bash<span class="pl-cce">\n</span>echo 'Hello World'"</span>
}</pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Gap 4: Self-Registration with nullboiler (MEDIUM PRIORITY)</h3><a id="user-content-gap-4-self-registration-with-nullboiler-medium-priority" class="anchor" aria-label="Permalink: Gap 4: Self-Registration with nullboiler (MEDIUM PRIORITY)" href="#gap-4-self-registration-with-nullboiler-medium-priority"><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"><strong>Problem:</strong> nullclaw cannot automatically register itself as a nullboiler worker on startup.</p>
<p dir="auto"><strong>Current State:</strong></p>
<ul dir="auto">
<li>nullboiler has <code>POST /workers</code> endpoint (<code>nullboiler/src/api.zig:135</code>)</li>
<li>nullclaw has no startup registration logic</li>
</ul>
<p dir="auto"><strong>Required:</strong></p>
<ul dir="auto">
<li>Config additions: <code>nullboiler.url</code>, <code>nullboiler.worker_id</code>, <code>nullboiler.tags</code>, <code>nullboiler.capacity</code></li>
<li>Startup hook in <code>nullclaw/src/daemon.zig</code> or new <code>nullclaw/src/boiler_client.zig</code></li>
<li>HTTP POST to <code>{nullboiler_url}/workers</code> with registration payload</li>
</ul>
<p dir="auto"><strong>Implementation Notes:</strong></p>
<div class="highlight highlight-source-zig notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// Registration payload
{
  &quot;id&quot;: &quot;nullclaw-coder-1&quot;,
  &quot;url&quot;: &quot;http://nullclaw:8080/api/worker&quot;,
  &quot;protocol&quot;: &quot;webhook&quot;,
  &quot;tags&quot;: [&quot;coder&quot;, &quot;bash&quot;],
  &quot;max_concurrent&quot;: 3
}"><pre><span class="pl-c">// Registration payload</span>
{
  <span class="pl-s">"id"</span>: <span class="pl-s">"nullclaw-coder-1"</span>,
  <span class="pl-s">"url"</span>: <span class="pl-s">"http://nullclaw:8080/api/worker"</span>,
  <span class="pl-s">"protocol"</span>: <span class="pl-s">"webhook"</span>,
  <span class="pl-s">"tags"</span>: [<span class="pl-s">"coder"</span>, <span class="pl-s">"bash"</span>],
  <span class="pl-s">"max_concurrent"</span>: <span class="pl-c1">3</span>
}</pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Gap 5: Dedicated Workflow Tool (MEDIUM PRIORITY)</h3><a id="user-content-gap-5-dedicated-workflow-tool-medium-priority" class="anchor" aria-label="Permalink: Gap 5: Dedicated Workflow Tool (MEDIUM PRIORITY)" href="#gap-5-dedicated-workflow-tool-medium-priority"><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"><strong>Problem:</strong> Orchestrator agent must manually construct nullboiler API calls using <code>http_request</code> tool, which is error-prone.</p>
<p dir="auto"><strong>Current State:</strong></p>
<ul dir="auto">
<li>nullboiler <code>POST /runs</code> endpoint exists (<code>nullboiler/src/api.zig:70</code>)</li>
<li>nullclaw <code>http_request</code> tool can make arbitrary calls</li>
<li>No high-level workflow abstraction</li>
</ul>
<p dir="auto"><strong>Required:</strong></p>
<ul dir="auto">
<li>New <code>create_workflow</code> tool in <code>nullclaw/src/tools/workflow.zig</code></li>
<li>Wrap nullboiler <code>POST /runs</code> API</li>
<li>Auto-set callback URL to nullclaw's gateway</li>
<li>Simplified interface for agent</li>
</ul>
<p dir="auto"><strong>Implementation Notes:</strong></p>
<div class="highlight highlight-source-zig notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// Tool interface
{
  &quot;name&quot;: &quot;create_workflow&quot;,
  &quot;arguments&quot;: {
    &quot;workflow_name&quot;: &quot;code-review&quot;,
    &quot;inputs&quot;: {&quot;task&quot;: &quot;Create bash script&quot;},
    &quot;telegram_target&quot;: &quot;-100123#topic:456&quot;
  }
}"><pre><span class="pl-c">// Tool interface</span>
{
  <span class="pl-s">"name"</span>: <span class="pl-s">"create_workflow"</span>,
  <span class="pl-s">"arguments"</span>: {
    <span class="pl-s">"workflow_name"</span>: <span class="pl-s">"code-review"</span>,
    <span class="pl-s">"inputs"</span>: {<span class="pl-s">"task"</span>: <span class="pl-s">"Create bash script"</span>},
    <span class="pl-s">"telegram_target"</span>: <span class="pl-s">"-100123#topic:456"</span>
  }
}</pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Gap 6: Topic-Aware Callback Routing (MEDIUM PRIORITY)</h3><a id="user-content-gap-6-topic-aware-callback-routing-medium-priority" class="anchor" aria-label="Permalink: Gap 6: Topic-Aware Callback Routing (MEDIUM PRIORITY)" href="#gap-6-topic-aware-callback-routing-medium-priority"><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"><strong>Problem:</strong> When nullboiler sends a callback, nullclaw needs to know which Telegram topic to route the result to.</p>
<p dir="auto"><strong>Current State:</strong></p>
<ul dir="auto">
<li>Callbacks contain run/step metadata but no Telegram routing info</li>
<li>Agent bindings config has topic mappings</li>
</ul>
<p dir="auto"><strong>Required:</strong></p>
<ul dir="auto">
<li>Store <code>telegram_target</code> (chat_id#topic) in run metadata when creating workflow</li>
<li>Include in callback payload or correlate via run_id</li>
<li>Callback receiver looks up target and routes via outbound bus</li>
</ul>
<p dir="auto"><strong>Implementation Notes:</strong></p>
<div class="highlight highlight-source-zig notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// Store in run creation
POST /runs
{
  &quot;workflow&quot;: {...},
  &quot;inputs&quot;: {...},
  &quot;metadata&quot;: {
    &quot;telegram_target&quot;: &quot;-100123#topic:456&quot;,
    &quot;origin_chat_id&quot;: &quot;-100123&quot;,
    &quot;origin_topic_id&quot;: &quot;42&quot;
  }
}"><pre><span class="pl-c">// Store in run creation</span>
<span class="pl-v">POST</span> <span class="pl-k">/</span><span class="pl-v">runs</span>
{
  <span class="pl-s">"workflow"</span>: {<span class="pl-k">...</span>},
  <span class="pl-s">"inputs"</span>: {<span class="pl-k">...</span>},
  <span class="pl-s">"metadata"</span>: {
    <span class="pl-s">"telegram_target"</span>: <span class="pl-s">"-100123#topic:456"</span>,
    <span class="pl-s">"origin_chat_id"</span>: <span class="pl-s">"-100123"</span>,
    <span class="pl-s">"origin_topic_id"</span>: <span class="pl-s">"42"</span>
  }
}</pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Gap 7: nulltickets Push Notifications (LOW PRIORITY)</h3><a id="user-content-gap-7-nulltickets-push-notifications-low-priority" class="anchor" aria-label="Permalink: Gap 7: nulltickets Push Notifications (LOW PRIORITY)" href="#gap-7-nulltickets-push-notifications-low-priority"><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"><strong>Problem:</strong> nulltickets is pull-based (lease/claim). No push/webhook mechanism for real-time notifications.</p>
<p dir="auto"><strong>Current State:</strong></p>
<ul dir="auto">
<li>nulltickets API: claim tasks via <code>POST /leases/claim</code></li>
<li>No webhook subscription endpoint</li>
</ul>
<p dir="auto"><strong>Impact:</strong> Low — nullboiler already bridges via <code>tracker_client.zig</code> polling</p>
<p dir="auto"><strong>Required (if needed):</strong></p>
<ul dir="auto">
<li>New webhook subscription API in <code>nulltickets/src/api.zig</code></li>
<li>Fire webhooks on stage transitions</li>
</ul>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Implementation Roadmap</h2><a id="user-content-implementation-roadmap" class="anchor" aria-label="Permalink: Implementation Roadmap" href="#implementation-roadmap"><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="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Phase 1: Critical Path (Gaps 1-3)</h3><a id="user-content-phase-1-critical-path-gaps-1-3" class="anchor" aria-label="Permalink: Phase 1: Critical Path (Gaps 1-3)" href="#phase-1-critical-path-gaps-1-3"><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">Without these, nullboiler cannot communicate with nullclaw at all.</p>
<ol dir="auto">
<li>
<p dir="auto"><strong>Worker Endpoint</strong> (<code>POST /api/worker</code>)</p>
<ul dir="auto">
<li>Accept nullboiler step dispatch</li>
<li>Route to agent via session manager</li>
<li>Return synchronous response</li>
<li>File: <code>nullclaw/src/gateway.zig</code></li>
</ul>
</li>
<li>
<p dir="auto"><strong>External Send API</strong> (<code>POST /api/send</code>)</p>
<ul dir="auto">
<li>Accept authenticated requests to send messages</li>
<li>Hook into outbound bus</li>
<li>Support topic format <code>chatid#topic:threadid</code></li>
<li>File: <code>nullclaw/src/gateway.zig</code></li>
</ul>
</li>
<li>
<p dir="auto"><strong>Callback Receiver</strong> (<code>POST /api/callback</code>)</p>
<ul dir="auto">
<li>Accept nullboiler callbacks</li>
<li>Parse event types</li>
<li>Route to appropriate handler</li>
<li>File: <code>nullclaw/src/gateway.zig</code></li>
</ul>
</li>
</ol>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Phase 2: Feedback Loop (Gaps 2+6)</h3><a id="user-content-phase-2-feedback-loop-gaps-26" class="anchor" aria-label="Permalink: Phase 2: Feedback Loop (Gaps 2+6)" href="#phase-2-feedback-loop-gaps-26"><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">Close the loop so workflow results reach the right Telegram topic.</p>
<ol start="4" dir="auto">
<li><strong>Topic-Aware Routing</strong>
<ul dir="auto">
<li>Store telegram_target in run metadata</li>
<li>Callback receiver extracts and routes</li>
<li>Integration with agent bindings</li>
<li>Files: <code>nullclaw/src/gateway.zig</code>, <code>nullboiler</code> run creation</li>
</ul>
</li>
</ol>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Phase 3: Automation (Gap 4)</h3><a id="user-content-phase-3-automation-gap-4" class="anchor" aria-label="Permalink: Phase 3: Automation (Gap 4)" href="#phase-3-automation-gap-4"><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>
<ol start="5" dir="auto">
<li><strong>Self-Registration</strong>
<ul dir="auto">
<li>Config schema additions</li>
<li>Startup registration logic</li>
<li>Health check pings</li>
<li>File: <code>nullclaw/src/daemon.zig</code></li>
</ul>
</li>
</ol>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Phase 4: Usability (Gap 5)</h3><a id="user-content-phase-4-usability-gap-5" class="anchor" aria-label="Permalink: Phase 4: Usability (Gap 5)" href="#phase-4-usability-gap-5"><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>
<ol start="6" dir="auto">
<li><strong>Workflow Tool</strong>
<ul dir="auto">
<li>High-level tool for orchestrator agents</li>
<li>Auto-configure callbacks</li>
<li>Schema validation</li>
<li>File: <code>nullclaw/src/tools/workflow.zig</code></li>
</ul>
</li>
</ol>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Phase 5: Enhancement (Gap 7)</h3><a id="user-content-phase-5-enhancement-gap-7" class="anchor" aria-label="Permalink: Phase 5: Enhancement (Gap 7)" href="#phase-5-enhancement-gap-7"><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>
<ol start="7" dir="auto">
<li><strong>nulltickets Push</strong> (optional)
<ul dir="auto">
<li>Webhook subscription API</li>
<li>Stage transition events</li>
<li>File: <code>nulltickets/src/api.zig</code></li>
</ul>
</li>
</ol>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Technical Details</h2><a id="user-content-technical-details" class="anchor" aria-label="Permalink: Technical Details" href="#technical-details"><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="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">nullclaw Gateway API Design</h3><a id="user-content-nullclaw-gateway-api-design" class="anchor" aria-label="Permalink: nullclaw Gateway API Design" href="#nullclaw-gateway-api-design"><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-zig notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// New endpoints to add in nullclaw/src/gateway.zig

// 1. Worker endpoint for nullboiler dispatch
POST /api/worker
Content-Type: application/json
Authorization: Bearer &lt;token&gt;

Request:
{
  &quot;prompt&quot;: &quot;Generate a bash script that...&quot;,
  &quot;context&quot;: {&quot;previous_output&quot;: &quot;...&quot;},
  &quot;step_id&quot;: &quot;code&quot;,
  &quot;run_id&quot;: &quot;run-uuid&quot;,
  &quot;correlation_id&quot;: &quot;corr-uuid&quot;
}

Response:
{
  &quot;status&quot;: &quot;ok&quot;,
  &quot;response&quot;: &quot;#!/bin/bash\necho 'Hello World'&quot;,
  &quot;correlation_id&quot;: &quot;corr-uuid&quot;
}

// 2. External message send
POST /api/send
Content-Type: application/json
Authorization: Bearer &lt;token&gt;

Request:
{
  &quot;channel&quot;: &quot;telegram&quot;,
  &quot;chat_id&quot;: &quot;-1001234567890#topic:42&quot;,
  &quot;content&quot;: &quot;Task completed successfully!&quot;,
  &quot;reply_to_message_id&quot;: null
}

Response:
{
  &quot;status&quot;: &quot;ok&quot;,
  &quot;message_id&quot;: &quot;12345&quot;
}

// 3. Callback receiver
POST /api/callback
Content-Type: application/json
Authorization: Bearer &lt;token&gt;

Request:
{
  &quot;event&quot;: &quot;step.completed&quot;,
  &quot;run_id&quot;: &quot;run-uuid&quot;,
  &quot;step_id&quot;: &quot;code&quot;,
  &quot;output&quot;: &quot;Generated script content...&quot;,
  &quot;metadata&quot;: {
    &quot;telegram_target&quot;: &quot;-100123#topic:42&quot;
  }
}

Response:
{
  &quot;status&quot;: &quot;received&quot;
}"><pre><span class="pl-c">// New endpoints to add in nullclaw/src/gateway.zig</span>

<span class="pl-c">// 1. Worker endpoint for nullboiler dispatch</span>
<span class="pl-v">POST</span> <span class="pl-k">/</span><span class="pl-v">api</span><span class="pl-k">/</span><span class="pl-v">worker</span>
<span class="pl-en">Content</span><span class="pl-k">-</span><span class="pl-smi">Type</span>: <span class="pl-v">application</span><span class="pl-k">/</span><span class="pl-k">json</span>
<span class="pl-smi">Authorization</span>: <span class="pl-en">Bearer</span> <span class="pl-k">&lt;</span><span class="pl-v">token</span><span class="pl-k">&gt;</span>

<span class="pl-smi">Request</span>:
{
  <span class="pl-s">"prompt"</span>: <span class="pl-s">"Generate a bash script that..."</span>,
  <span class="pl-s">"context"</span>: {<span class="pl-s">"previous_output"</span>: <span class="pl-s">"..."</span>},
  <span class="pl-s">"step_id"</span>: <span class="pl-s">"code"</span>,
  <span class="pl-s">"run_id"</span>: <span class="pl-s">"run-uuid"</span>,
  <span class="pl-s">"correlation_id"</span>: <span class="pl-s">"corr-uuid"</span>
}

<span class="pl-smi">Response</span>:
{
  <span class="pl-s">"status"</span>: <span class="pl-s">"ok"</span>,
  <span class="pl-s">"response"</span>: <span class="pl-s">"#!/bin/bash<span class="pl-cce">\n</span>echo 'Hello World'"</span>,
  <span class="pl-s">"correlation_id"</span>: <span class="pl-s">"corr-uuid"</span>
}

<span class="pl-c">// 2. External message send</span>
<span class="pl-v">POST</span> <span class="pl-k">/</span><span class="pl-v">api</span><span class="pl-k">/</span><span class="pl-v">send</span>
<span class="pl-en">Content</span><span class="pl-k">-</span><span class="pl-smi">Type</span>: <span class="pl-v">application</span><span class="pl-k">/</span><span class="pl-k">json</span>
<span class="pl-smi">Authorization</span>: <span class="pl-en">Bearer</span> <span class="pl-k">&lt;</span><span class="pl-v">token</span><span class="pl-k">&gt;</span>

<span class="pl-smi">Request</span>:
{
  <span class="pl-s">"channel"</span>: <span class="pl-s">"telegram"</span>,
  <span class="pl-s">"chat_id"</span>: <span class="pl-s">"-1001234567890#topic:42"</span>,
  <span class="pl-s">"content"</span>: <span class="pl-s">"Task completed successfully!"</span>,
  <span class="pl-s">"reply_to_message_id"</span>: <span class="pl-c1">null</span>
}

<span class="pl-smi">Response</span>:
{
  <span class="pl-s">"status"</span>: <span class="pl-s">"ok"</span>,
  <span class="pl-s">"message_id"</span>: <span class="pl-s">"12345"</span>
}

<span class="pl-c">// 3. Callback receiver</span>
<span class="pl-v">POST</span> <span class="pl-k">/</span><span class="pl-v">api</span><span class="pl-k">/</span><span class="pl-v">callback</span>
<span class="pl-en">Content</span><span class="pl-k">-</span><span class="pl-smi">Type</span>: <span class="pl-v">application</span><span class="pl-k">/</span><span class="pl-k">json</span>
<span class="pl-smi">Authorization</span>: <span class="pl-en">Bearer</span> <span class="pl-k">&lt;</span><span class="pl-v">token</span><span class="pl-k">&gt;</span>

<span class="pl-smi">Request</span>:
{
  <span class="pl-s">"event"</span>: <span class="pl-s">"step.completed"</span>,
  <span class="pl-s">"run_id"</span>: <span class="pl-s">"run-uuid"</span>,
  <span class="pl-s">"step_id"</span>: <span class="pl-s">"code"</span>,
  <span class="pl-s">"output"</span>: <span class="pl-s">"Generated script content..."</span>,
  <span class="pl-s">"metadata"</span>: {
    <span class="pl-s">"telegram_target"</span>: <span class="pl-s">"-100123#topic:42"</span>
  }
}

<span class="pl-smi">Response</span>:
{
  <span class="pl-s">"status"</span>: <span class="pl-s">"received"</span>
}</pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">nullboiler Integration Points</h3><a id="user-content-nullboiler-integration-points" class="anchor" aria-label="Permalink: nullboiler Integration Points" href="#nullboiler-integration-points"><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-zig notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// nullboiler/src/callbacks.zig - existing callback firing
// This already works, just needs a target endpoint

pub fn fireCallbacks(
    allocator: std.mem.Allocator,
    callbacks: []const Callback,
    event: Event,
    run_id: []const u8,
    step_id: ?[]const u8,
    output: ?[]const u8,
) !void {
    // Callback POST to nullclaw /api/callback
    // Include telegram_target from run metadata
}"><pre><span class="pl-c">// nullboiler/src/callbacks.zig - existing callback firing</span>
<span class="pl-c">// This already works, just needs a target endpoint</span>

<span class="pl-k">pub</span> <span class="pl-k">fn</span> <span class="pl-en">fireCallbacks</span>(
    <span class="pl-v">allocator</span>: <span class="pl-k">std.mem.Allocator</span>,
    <span class="pl-v">callbacks</span>: []<span class="pl-k">const</span> <span class="pl-k">Callback</span>,
    <span class="pl-v">event</span>: <span class="pl-k">Event</span>,
    <span class="pl-v">run_id</span>: []<span class="pl-k">const</span> <span class="pl-k">u8</span>,
    <span class="pl-v">step_id</span>: <span class="pl-k">?</span>[]<span class="pl-k">const</span> <span class="pl-k">u8</span>,
    <span class="pl-v">output</span>: <span class="pl-k">?</span>[]<span class="pl-k">const</span> <span class="pl-k">u8</span>,
) <span class="pl-k">!</span><span class="pl-k">void</span> {
    <span class="pl-c">// Callback POST to nullclaw /api/callback</span>
    <span class="pl-c">// Include telegram_target from run metadata</span>
}</pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Data Flow Example</h3><a id="user-content-data-flow-example" class="anchor" aria-label="Permalink: Data Flow Example" href="#data-flow-example"><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="User in General topic:
  &quot;Write a bash script that backs up my home directory&quot;

1. nullclaw receives via Telegram webhook
2. Agent &quot;orchestrator&quot; processes message
3. Agent calls create_workflow tool
   → POST to nullboiler /runs
   → Metadata includes: telegram_target=&quot;general#topic:1&quot;

nullboiler:
4. Creates workflow run
5. Dispatches &quot;code&quot; step to &quot;coder&quot; worker (nullclaw instance)
   → POST to nullclaw /api/worker

nullclaw (coder):
6. Receives step dispatch
7. Agent &quot;coder&quot; generates script
8. Returns response to nullboiler

nullboiler:
9. Step completes
10. Fires callback
    → POST to nullclaw /api/callback
    → Includes output + telegram_target

nullclaw:
11. Callback receiver parses event
12. Routes output to telegram_target
    → POST internally to /api/send
    → Delivers to General topic

User sees:
  [In General topic] &quot;Here's the backup script: ...&quot;"><pre class="notranslate"><code>User in General topic:
  "Write a bash script that backs up my home directory"

1. nullclaw receives via Telegram webhook
2. Agent "orchestrator" processes message
3. Agent calls create_workflow tool
   → POST to nullboiler /runs
   → Metadata includes: telegram_target="general#topic:1"

nullboiler:
4. Creates workflow run
5. Dispatches "code" step to "coder" worker (nullclaw instance)
   → POST to nullclaw /api/worker

nullclaw (coder):
6. Receives step dispatch
7. Agent "coder" generates script
8. Returns response to nullboiler

nullboiler:
9. Step completes
10. Fires callback
    → POST to nullclaw /api/callback
    → Includes output + telegram_target

nullclaw:
11. Callback receiver parses event
12. Routes output to telegram_target
    → POST internally to /api/send
    → Delivers to General topic

User sees:
  [In General topic] "Here's the backup script: ..."
</code></pre></div>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Configuration Example</h2><a id="user-content-configuration-example" class="anchor" aria-label="Permalink: Configuration Example" href="#configuration-example"><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-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// nullclaw config.json additions
{
  &quot;nullboiler&quot;: {
    &quot;url&quot;: &quot;http://nullboiler:8080&quot;,
    &quot;worker_id&quot;: &quot;nullclaw-main&quot;,
    &quot;tags&quot;: [&quot;orchestrator&quot;, &quot;general&quot;],
    &quot;max_concurrent&quot;: 5,
    &quot;auto_register&quot;: true
  },
  &quot;gateway&quot;: {
    &quot;enable_worker_endpoint&quot;: true,
    &quot;enable_callback_endpoint&quot;: true,
    &quot;enable_send_api&quot;: true
  }
}"><pre><span class="pl-ii">// nullclaw config.json additions</span>
{
  <span class="pl-ent">"nullboiler"</span>: {
    <span class="pl-ent">"url"</span>: <span class="pl-s"><span class="pl-pds">"</span>http://nullboiler:8080<span class="pl-pds">"</span></span>,
    <span class="pl-ent">"worker_id"</span>: <span class="pl-s"><span class="pl-pds">"</span>nullclaw-main<span class="pl-pds">"</span></span>,
    <span class="pl-ent">"tags"</span>: [<span class="pl-s"><span class="pl-pds">"</span>orchestrator<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>general<span class="pl-pds">"</span></span>],
    <span class="pl-ent">"max_concurrent"</span>: <span class="pl-c1">5</span>,
    <span class="pl-ent">"auto_register"</span>: <span class="pl-c1">true</span>
  },
  <span class="pl-ent">"gateway"</span>: {
    <span class="pl-ent">"enable_worker_endpoint"</span>: <span class="pl-c1">true</span>,
    <span class="pl-ent">"enable_callback_endpoint"</span>: <span class="pl-c1">true</span>,
    <span class="pl-ent">"enable_send_api"</span>: <span class="pl-c1">true</span>
  }
}</pre></div>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Files Modified</h2><a id="user-content-files-modified" class="anchor" aria-label="Permalink: Files Modified" href="#files-modified"><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>Project</th>
<th>File</th>
<th>Changes</th>
</tr>
</thead>
<tbody>
<tr>
<td>nullclaw</td>
<td><code>src/gateway.zig</code></td>
<td>Add 3 new endpoints: /api/worker, /api/send, /api/callback</td>
</tr>
<tr>
<td>nullclaw</td>
<td><code>src/config.zig</code></td>
<td>Add nullboiler config struct</td>
</tr>
<tr>
<td>nullclaw</td>
<td><code>src/daemon.zig</code></td>
<td>Add self-registration startup hook</td>
</tr>
<tr>
<td>nullclaw</td>
<td><code>src/tools/workflow.zig</code></td>
<td>New tool for create_workflow</td>
</tr>
<tr>
<td>nullclaw</td>
<td><code>src/tools/root.zig</code></td>
<td>Register workflow tool</td>
</tr>
<tr>
<td>nullboiler</td>
<td><code>src/api.zig</code></td>
<td>Optionally include telegram_target in run metadata</td>
</tr>
<tr>
<td>nulltickets</td>
<td><code>src/api.zig</code></td>
<td>Optional: webhook subscriptions (low priority)</td>
</tr>
</tbody>
</table></markdown-accessiblity-table>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">References</h2><a id="user-content-references" class="anchor" aria-label="Permalink: References" href="#references"><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="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">nullclaw</h3><a id="user-content-nullclaw" class="anchor" aria-label="Permalink: nullclaw" href="#nullclaw"><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><code>src/gateway.zig</code> - HTTP server and routing</li>
<li><code>src/agent/root.zig</code> - Agent execution</li>
<li><code>src/session.zig</code> - Session management</li>
<li><code>src/agent_bindings_config.zig</code> - Topic binding resolution</li>
<li><code>src/tools/message.zig</code> - Message sending</li>
<li><code>src/channels/telegram.zig</code> - Telegram topic support</li>
</ul>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">nullboiler</h3><a id="user-content-nullboiler" class="anchor" aria-label="Permalink: nullboiler" href="#nullboiler"><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><code>src/engine.zig</code> - DAG execution loop</li>
<li><code>src/dispatch.zig</code> - Worker dispatch logic</li>
<li><code>src/callbacks.zig</code> - Callback firing mechanism</li>
<li><code>src/api.zig</code> - REST API endpoints</li>
<li><code>src/types.zig</code> - Step types and data structures</li>
</ul>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">nulltickets</h3><a id="user-content-nulltickets" class="anchor" aria-label="Permalink: nulltickets" href="#nulltickets"><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><code>src/api.zig</code> - REST API</li>
<li><code>src/store.zig</code> - Database operations</li>
<li><code>src/domain.zig</code> - FSM transitions</li>
</ul>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Version History</h2><a id="user-content-version-history" class="anchor" aria-label="Permalink: Version History" href="#version-history"><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>Date</th>
<th>Author</th>
<th>Changes</th>
</tr>
</thead>
<tbody>
<tr>
<td>2026-03-13</td>
<td>@vedmalex</td>
<td>Initial gap analysis based on codebase exploration</td>
</tr>
</tbody>
</table></markdown-accessiblity-table>
<hr>
<p dir="auto"><em>This document is a living analysis. As implementations progress, update the status of each gap and add implementation notes.</em></p>
</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>

