Microsoft

Stars and mentions

Last 30 days, Oct 5 – Nov 3

GitHub stars33,278
mentions969
06541.3K2K2.6KOct 5Oct 19Nov 3
UTC days · repositories Microsoft owns331 repositories

Package downloads

Cumulative recorded downloads · since 2025-10-17

crates.io—
npm47B
PyPI—
011.8B23.5B35.3B47BOct 5Oct 19Nov 3
Nov 2crates.io: 0/139 packages observed · npm: 3/265 packages observed · PyPI: 0/96 packages observed

Across 500 known packages in repositories Microsoft owns. Cumulative totals include recorded downloads before the selected range. Missing observations leave gaps; totals may be incomplete. PyPI excludes known mirrors.

Top repositories

Microsoft’s repositories ranked by new forks, as on trending.

Loading

Contributes to

Repositories outside Microsoft’s account where Microsoft opened or reviewed pull requests in the past 365 days.

Who noticed Microsoft

Everyone who starred or forked Microsoft’s repositories since the archive began in 2011.

Notable accounts

Ordered by the stars their own repositories have received.

Biggest fans

Accounts that starred the most of these repositories.

Breakout weeks

Each repository’s best week of new stars, with the release published around it.

Mentions

966posts
Nov 41 post
  1. GraphRAG論文を実装目線で読む:事前要約とGlobal Searchの境界 GraphRAGを実装目線で読むと、気になるのはグラフの形だけでなく、質問前に何を作り、質問時に何をモデルへ渡すのかです。 この記事では、Darren EdgeらのFrom Local to Global: A GraphRAG Approach to Query-Focused Summarization v2とMicrosoftの公式資料を基に、この境界を整理します。原論文の中心であるGlobal Searchと、公式実装のLocal Searchを区別して扱います。 RAG(検索した外部情報を生成モデルの回答に使う方法)の基本は、ブログのRAGと外部知識の解説を参照してください。以下は資料読解による技術メモで、ライブラリの実行や性能測定はしていません。 通常のRAGとの違いを架空の案件資料から追う説明や、用語ごとの図解は、ブログのGraphRAG解説にまとめています。ここでは中間成果物と検索処理の設計に焦点を当てます。 検索上位の文章は、資料全体の代表とは限らない 「案件Aの担当者は誰か」なら、該当する文章を取得する構成が自然です。一方、「全案件に共通する遅延要因は何か」では、質問に似た文章を上位から取得しても、別の種類の要因が抜ける可能性があります。 GraphRAGの原論文が扱うのは、このような資料全体の理解を要する質問です。関連性だけで選んだ断片に依存せず、関係のまとまりから事前に作った要約を回答の材料にします。 ただし、比較対象は原論文のベクトル検索によるRAGです。複数回の検索や多様性を考慮した取得など、あらゆるRAG構成に対する優位性を示したものではありません。 中間成果物を、役割ごとに分けて読む Microsoftの標準的な索引作成処理は、LLM(大規模言語モデル)で対象や関係を抽出し、そのまとまりを要約します。以下は、公式のDataflowを読むために整理した表です。列名や保存形式を固定する実装仕様ではありません。 成果物 主に保持するもの 設計上、確認したい点 Text units 分割した元の文章 元資料の位置へ戻れるか Entities 人物・組織などの対象と説明 表記違いや同名対象をどう扱うか Relationships 対象間の関係と説明 元資料に記載された関係か、抽出時の誤りか Communities 関係の密な対象のまとまりと階層 分類の粒度が用途に合うか Community reports まとまりごとの内容を整理した要約 元の説明や重要な例外が落ちていないか コミュニティは、元ファイルを部署別に分類したものとは限りません。グラフ上の対象をまとめるため、一つの資料から複数のまとまりに関係する情報が得られることもあります。 原論文と公式資料の概念を基に独自作成した架空例です。実際の検出結果ではなく、階層構造も省略しています。 この区別は更新処理を考えるときにも役立ちます。元資料を修正したら、その文章だけでなく、影響を受けた対象の説明や要約まで古くなり得ます。具体的にどこまで再計算するかは実装によりますが、元資料と派生した情報の対応を追えることを評価項目にしたいところです。 なお、現行資料ではClaims(資料中の主張)の抽出は任意です。論文の概念図に登場するものを、すべての設定で必須の処理だと解釈しないようにします。 Global Search:事前要約と部分回答は別の成果物 Global Searchでは、指定した階層のコミュニティレポートを利用します。概念上の流れは次のとおりです。 レポート集合を、処理できる長さの要約群へ分割する。 各要約群と同じ質問をモデルへ渡し、質問に対する部分回答を作る。 有用性を評価して内容を絞り込み、最終回答の文脈に収める。 選んだ部分回答を使って全体の回答を生成する。 これはMap-Reduce(分割処理した結果を統合する方法)の構成です。実装では、要約群を作る処理、部分回答の生成、選別、最終生成を分けて読むと、どこで情報が落ちたかを追いやすくなります。 原論文と公式Global Searchを基にした独自模式図です。各部分回答には、同じ質問と異なる要約群の両方が入力されます。 事前要約は資料を整理したもので、部分回答は今回の質問に依存します。そのため、質問を変えると部分回答も変わりますが、資料・抽出設定・要約設定が同じなら事前要約を再利用する設計ができます。 ここで注意したいのは、グラフ全体をそのまま最終生成モデルへ渡すわけではないことです。レポートの分割、部分回答の選別、最終文脈の長さという段階ごとの制約があります。情報を広く扱うための構成でも、全事実が回答に残る保証はありません。 公式資料では、細かな階層のレポートほど詳細な回答につながり得る一方、レポート数に応じて処理時間やモデル利用量が増える可能性を説明しています。公式Global Search Local Searchとの違いは、取得の入口にもある Local Searchは、質問と意味の近いエンティティを入口にし、関連する対象・関係・元の文章などを集めます。Global Searchの処理を、対象の数だけ少なくしたものと考えると、この違いを見落とします。公式Local Search 比較軸 Local Search Global Search 入口 質問に関連する対象 指定階層のコミュニティレポート 主な文脈 対象の関係情報と関連文章など 要約群から作る部分回答 向く質問の例 特定の案件に関わる部署と役割 案件群全体で繰り返される課題 確認したい失敗 入口となる対象の取り違え 要約・選別での重要論点の脱落 GraphRAGでも意味の近さによる検索は使われます。「ベクトル検索かグラフか」の二択より、どの情報を入口に、何を組み合わせるかを見るほうが設計を理解しやすいと感じます。 評価では、グラフなしの全体要約も比較する 原論文v2は、ニュースとポッドキャストの二つの資料群に対して、LLMで作った各125問の全体理解を問う質問を使っています。包括性と多様性ではベクトルRAGに対する改善を報告していますが、簡潔で直接的な回答ではベクトルRAGが優位でした。 さらに、グラフを作らず元の文章を分割して要約・統合する方法も比較しています。この比較は、全体を扱った効果と、グラフを使った効果を考えるうえで重要です。 自分の用途で試すなら、以下の比較を置きたいと考えます。これは筆者の評価案です。 比較対象 確かめたいこと 負担・弱点 関連文章を取得するRAG 小範囲の根拠で答えられるか 全体の論点が抜ける可能性 元文章の分割要約と統合 グラフなしでも全体質問に答えられるか 質問ごとに広い文章範囲を処理する負担 GraphRAGのGlobal Search 事前要約の再利用と回答品質が両立するか 抽出・要約の準備と更新管理 評価点も一つにまとめず、根拠との一致、論点の取りこぼし、応答時間、初回準備、資料更新時の負担を分けます。包括性の評価が高いことを、そのまま事実の正確性や捏造率の改善とは扱えません。原論文も一般化や捏造率の比較に追加検証が必要だとしています。原論文v2・評価と限界 所感:モデルの前に、文脈を作る処理を設計する この論文で参考になるのは、全体を問う質問のために、検索時に渡す文脈を事前処理から設計している点です。グラフを作っただけで回答が良くなるというより、関係をまとめた要約を、質問ごとの部分回答へ変換する構成に意味があります。 採用判断では、その構成が手元の質問に必要かを確かめたいです。担当者や日付を取り出す用途と、複数資料を横断する調査では、比較すべき品質も許容できる負担も変わります。 実装を利用する場合、公式READMEは索引作成が高コストになり得るため、小さく始めるよう案内しています。また、2026年9月14日の確認時点では保守中心の方針が記載されており、新機能追加や新しいプルリクエストの受け付けは行わないとされています。Microsoftが正式にサポートする製品ではないことも明記されています。Microsoft GraphRAG公式リポジトリ 参考資料 Darren Edgeほか:From Local to Global: A GraphRAG Approach to Query-Focused Summarization v2(CC BY 4.0) Microsoft GraphRAG:Dataflow Microsoft GraphRAG:Global Search Microsoft GraphRAG:Local Search Microsoft GraphRAG:公式リポジトリ

  2. AIエージェントのMCP承認。許可リストに無いツールは承認なしだった Microsoft Agent Framework(PythonでAIエージェントを作るMicrosoftのライブラリ)で、ローカルのMCPサーバーをつなぐ人向けの話です。10月30日公開のpython-1.24.0(リリースノート記載)で、MCPツールの承認設定に default が加わりました。always_require_approval と never_require_approval のどちらにも書かないツールは、これまでどう扱われていたのか。そこが気になって試しました。 そこで、読み取り用2つと削除用1つのツールを持つMCPサーバーを用意し、承認設定を5通りに変えて、ツールごとの承認モードを出力しました。never_require_approval に読み取り系だけを書くと、書いていない削除ツールの承認モードも never_require になりました。 ! 2026-11-04、macOS・Python 3.13・agent-framework-core 1.24.0・mcp 2.3.0で確認しました。見たのは、接続後に各ツールへ付く承認モード(approval_mode)の値です。LLMを載せたエージェント実行で承認の確認が実際に出る様子までは見ていません。 試した構成 MCPサーバーはPythonのFastMCPで作りました。ツールは read_note、search_notes、delete_note の3つです。これを MCPStdioTool で接続し、接続後の functions から各ツールの approval_mode を読みます。承認の設定だけを変えて5条件を並べました。 A=指定なし、B=neverだけ、C=Bにdefaultを追加、D=alwaysだけ、E=同じツールをalwaysとneverの両方へ。画像は端末風に整形したものです。 結果。Bの設定では、delete_noteも承認なしでした 出力が次の画像です。各条件の delete_note の行に注目してください。 Bだけが FutureWarning を出し、delete_note は never_require のままです。 条件 設定 delete_note A 指定なし 承認なし B never_require_approval に読み取り2つ 承認なし(FutureWarning) C Bに default: always_require を追加 承認が必要 D always_require_approval に delete_note 承認が必要 E delete_note を always と never の両方に 承認が必要(always が優先) Bは「読み取りは自動で通し、ほかは確認する」という意図に見える設定です。ところが、どちらのリストにも名前がないツールは、承認なしで通ります。出るのは FutureWarning だけで、動作そのものは変わりません。PRの説明によると、この警告は、将来この既定値が変わるかもしれないことへの予告です。 解決順と、直し方 PR #9828 の説明とMicrosoft Learnには、同じ判定順が書かれていました。まず always_require_approval、次に never_require_approval、最後に default を見ます。どれにも該当しなければ承認なしです。実測でも、リストに無いツールの扱い(B・C)と、alwaysがneverより優先されること(E)を確認でき、どちらも上の順序どおりでした。 直し方は、default を明示することです。 approval_mode={ "never_require_approval": ["read_note", "search_notes"], "default": "always_require", } これで、あとからMCPサーバーに追加されたツールも、名前を挙げない限り承認が必要になります。PRの説明では、tools/list_changed のあとに見つかったツールにも default が効くとされています。この点は、私の環境では試していません。 明日試すなら 手元のMCPサーバーで、never_require_approval だけを書いている箇所を探してください。あれば default を足し、接続後の approval_mode を出力してみてください。足す前と後で違いが見えます。用意するのは pip install "agent-framework-core==1.24.0" と、接続後の functions を読む数行のコードです。Pythonは3.11以上が対象です。私の環境では、これに加えて tenacity も入れる必要がありました。 参考 microsoft/agent-framework python-1.24.0 リリースノート PR #9828: Add a default approval mode to MCP approval policies Microsoft Learn: Local MCP tools(Agent Framework)

  3. arXiv · · cs.LG · Akram Zaytar · microsoft/pappi

    Crop Mapping Evaluation under Sampling Bias Government agencies use crop maps to estimate production, monitor food security, and set agricultural policy. These crop maps are usually validated against field labels, but these labels are rarely a random sample of the area the map covers. Field teams tend to label parcels near roads and skip ones that are small or hard to reach, so performance measured on held-out labels mainly describes the places they visited. We call the difference between this reported performance and performance over the whole mapped region the deployment performance gap. To estimate performance over the whole region, we use a weighted form of prediction-powered inference (PPI). The classifier's predictions on unlabeled points across the region give a first estimate, and its errors on the labeled points correct that estimate, with more weight on labels from under-sampled conditions. We test this in five European regions where crop registers label every declared parcel, so the true performance is known. Simulating six documented collection practices there produces gaps of up to 0.20 macro-F1. On the collection rule that creates the largest gap in each region, 5 km block cross-validation still overestimates macro-F1 by as much as 0.18, while PPI with weights estimated from satellite embeddings reduces the largest error across regions to 0.07. Importance-weighted cross-validation with the same weights does almost as well, so most of the improvement comes from the weights themselves. We also apply the method to three Kenyan datasets that have no region-wide reference labels. For a roadside dataset collected with helmet-mounted cameras, the estimated macro-F1 falls from 0.93 under random cross-validation to 0.61, although the correction relies on a small number of heavily weighted labels. Our code is available at microsoft/pappi. Comments: 17 pages, 4 figures, 5 tables. Code: microsoft/PaPPI

  4. .NET 8・.NET 9のサポート終了は2026年11月10日|同日終了の理由と.NET 10への移行ガイド Microsoftは標準期間サポート(STS)の期間を18か月から24か月に延長しました。その結果、.NET 9は.NET 8と同じ2026年11月10日にサポートが終了します。本記事では、その理由と.NET 10へのアップグレード方法を解説します。 .NET 9のサポートは2026年11月10日に終了します。.NET 8も同じ日です。残りは3週間を切りました。.NET 8は2023年11月14日にリリースされた長期サポート(LTS)版、.NET 9はその1年後の2024年11月12日にリリースされた標準期間サポート(STS)版です。この2つが同じ日にサポート終了を迎えます。誤植ではありません。11月10日以降にサポートされるバージョンは.NET 10で、LTSとして2028年11月14日までサポートされます。 2026年11月10日に.NET 8と.NET 9で何が終わるのか? 終わるのはサービシング(保守提供)です。.NET BlogでRahul Bhandari氏が公表した告知によると、Microsoftは.NET 8と.NET 9に対する「サービシング更新、セキュリティ修正、技術サポート」を終了します。 アプリケーションは引き続き動作します。自動でアンインストールされることもありません。ランタイム、SDK、コンテナイメージもダウンロードできます。ただし、今後は修正が提供されなくなります。 11月10日はパッチ・チューズデーでもあります。Microsoftによると、既知の重大な問題がある場合に限り、.NET 8と.NET 9は同日に最後の更新を1回ずつ受け取る可能性があります。それ以降は、ランタイム、ASP.NET Core、基底クラスライブラリ(BCL)に影響する新たなCVEはすべて自己責任で対処することになります。 本記事執筆時点の最新パッチは8.0.32と9.0.21で、どちらも2026年10月13日にリリースされています。これらを適用していない場合は、期限を迎える前から対応が遅れている状態です。 ツール面にも影響があります。今後のVisual Studio 2022のサービシング更新で、.NET 8と.NET 9のコンポーネントがサポート終了として扱われるようになります。Visual Studioは更新時に、サポート終了のコンポーネントの削除を提案します。ビルドエージェントでこの設定を事前に確認しておきましょう。 なぜ.NET 9は.NET 8と同じ日にサポートが終わるのか? .NET 9のサポート期間中に、MicrosoftがSTSのライフサイクルを変更したためです。 旧ポリシーでは、STSのサポート期間は18か月でした。これは次のリリースから6か月後にあたります。.NET 9は2026年5月12日にサポートが終了する予定でした。 2025年9月16日、.NET BlogでJamshed Damkewala氏が、STSリリースのサポート期間を24か月に延長すると発表しました。.NET 9から適用されます。LTSは従来どおり3年です。これにより、.NET 9のサポート終了日は2026年5月12日から2026年11月10日に移り、.NET 8の終了日とちょうど重なりました。 STSを24か月に延ばしたことで、STSリリースの終了日は直前のLTSリリースと同じになります。STS版の依存関係を使っていても、LTS版アプリと同じ日にサポートが終わる形です。なお、.NET Aspireのようなアウトオブバンド(OOB)コンポーネントは独自のライフサイクルを持つため、別途確認が必要です。 実際の問題を解消する、妥当な見直しだと私は考えています。一方で、副作用として2つのリリースが同じ日にサポートカレンダーから外れることになりました。.NET 9の終了を2026年5月と見込んで計画していた方は、6か月の猶予が増えていたことに気づいていないかもしれません。 この構造は今後も繰り返されます。偶数番号のLTSは11月にリリースされ、3年間サポートされます。奇数番号のSTSは翌年の11月にリリースされ、新ポリシーでは2年間サポートされます。どちらも同じ11月に終了します。.NET 10と.NET 11も、2028年11月に同じ日にサポートが終わると私は見ています。今回は例外ではなく、これからの標準パターンです。 各.NETバージョンのサポート状況は? 出典: .NET and .NET Core Support Policy(2026年10月19日時点) どのバージョンにアップグレードすべきか? .NET 10です。 現行のLTSリリースで、2028年11月14日までサポートされます。24か月のSTSポリシーのもとでは、.NET 11を待っても猶予は延びません。得られるのは、同じ月にサポートが終わると私が見ている、より新しいリリースだけです。 .NET 9をお使いなら、.NET 10へは1バージョン上げるだけで、多くの場合は小規模な変更で済みます。.NET 8をお使いなら、2リリース分の破壊的変更をまたぐため、工数を多めに見込んでください。ASP.NET Coreアプリは、ASP.NET Core 9から10への移行ガイドも確認しておきましょう。 最も単純な場合、アップグレードは各プロジェクトファイルの1行の変更です。 net10.0 ただし、この1行で済むことはまれです。実際の作業は次のような部分に生じます。 - 互換リリースが必要なNuGetパッケージ - 古いSDKを固定しているglobal.json - mcr.microsoft.com/dotnet/aspnet:8.0を参照しているDockerfile - 新しいランタイムのインストールが必要なCI/CDパイプラインとホスティング環境 自社で運用していても開発はしていないサードパーティ製アプリケーションについては、ベンダーに.NET 10対応版のリリースを問い合わせてください。 GitHub Copilotで.NET 10にアップグレードするには? .NET Upgrade Assistantは使いません。Microsoftのドキュメントでは、「.NET Upgrade Assistant is officially deprecated.」と明記されています。サポート終了の告知にはまだリンクが残っていて紛らわしいのですが、このツールは後継に置き換えられています。 後継はGitHub Copilot upgrade agentです。ソースコードとプラグインはmicrosoft/upgrade-agent-pluginsにあります。Mika Dumont氏がModernize .NET Anywhere with GitHub Copilotで使い方を解説しています。 作業は3つの段階で進みます。各段階の成果物はリポジトリの.github/upgrades/配下にMarkdownファイルとして出力されるので、レビューやコミットが可能です。 1. 評価(Assess): プロジェクトと依存関係を調べ、assessment.mdを出力します。破壊的変更、API互換性の問題、非推奨パターンが一覧化されます。 2. 計画(Plan): plan.mdを出力します。アップグレード戦略、依存関係の順序、リスクが記載されます。 3. 実行(Execute): 計画をtasks.mdのタスクに分割して順に実行し、作業単位ごとにGitコミットを作成します。検証やロールバックを段階的に行えます。 利用できる環境は4つあります。普段使っているものを選んでください。 - Visual Studio: Visual Studio 2026、またはVisual Studio 2022 17.14.16以降で、ソリューションエクスプローラーのソリューションまたはプロジェクトを右クリックし、Modernizeを選択します。 - VS Code: GitHub Copilot upgrade extensionをインストールし、Copilot ChatのエージェントピッカーでUpgradeを選択します。 - GitHub Copilot CLI: 次のコマンドを実行します。 /plugin marketplace add microsoft/upgrade-agent-plugins /plugin install upgrade-agent@upgrade-agent-plugins /agent Upgradeを選び、「upgrade my solution to .NET 10」のように指示します。 - GitHub: Copilotクラウドエージェントとして追加すると、プルリクエストを自動で作成できます。手順はクラウドエージェントのREADMEを参照してください。この方法には、クラウドエージェントが使える有料のCopilotプランと、リポジトリへの書き込み権限が必要です。 どの方法を選ぶにしても、次の点をおすすめします。 - 最初は、モノリスではなく小さなライブラリやサービスから始めましょう。自社のコードベースでエージェントがどこでつまずくかを把握できます。 - 大規模なコードでは、ガイドモード(Guided)を使いましょう。「pause」でガイドモードに、「continue」で自動モードに戻せます。 - 最後にまとめてではなく、コミットごとにテストスイート全体を実行しましょう。タスクごとにコミットされるため、コストを抑えられます。 - 完了後は、次のコマンドで結果を確認しましょう。 dotnet --list-runtimes dotnet list package --outdated 大規模なレガシーソリューションでは、エージェントが自力で最後までやり遂げられるとは限りません。大きなアプリで処理が止まるという初期ユーザーの報告もあり、Microsoftがリポジトリでフィードバックを集めています。移行の全工程ではなく、非常に速い初回パスとして使ってください。 2026年11月10日までに.NET 8・.NET 9からアップグレードできない場合は? その場合は、運用中のバージョンにパッチを提供してくれる存在が必要です。 HeroDevsのNever-Ending Support(NES)for .NETは、.NET 6、.NET 8、.NET 9をそのまま置き換えられる、安全なドロップイン代替です。ランタイム、ASP.NET、Entity Framework、.NET SDK、WPF、WinFormsを対象とし、NES for .NET Containersを使えばコンテナイメージもカバーします。コードの変更は不要です。 HeroDevsは.NET Security Groupのメンバーです。そのため、.NETに影響する脆弱性の事前開示を受け、MicrosoftのパッチTuesdayのリリースと同時に、EOLバージョン向けの修正済みビルドを提供できます。 これは仮定の話ではありません。.NET 6は2024年11月12日のサポート終了以来、HeroDevsがパッチを提供し続けています。System.Net.MailのSMTPインジェクションの脆弱性であるCVE-2026-32178では、.NET 6に上流の修正が提供されませんでしたが、NESのお客様には修正が提供されました。2026年11月11日からは、.NET 8と.NET 9もこの対象に加わります。 NESは.NET 10への移行の代わりにはなりません。移行のスケジュールを、パッチ・チューズデーではなく、エンジニアリングチームが決められるようになるということです。 よくある質問(FAQ) .NET 8と.NET 9のサポートが終了するのは正確にいつですか? どちらも2026年11月10日です。この日はパッチ・チューズデーで、既知の重大な問題がある場合に限り、Microsoftが各バージョンに最後の更新を1回提供する可能性があります。 .NET 9は2026年5月にサポート終了の予定ではなかったですか? はい、旧ポリシー(STS 18か月)では2026年5月12日でした。Microsoftが2025年9月16日にSTSを24か月に延長し(.NET 9から適用)、終了日が2026年11月10日に移りました。 .NET 8や.NET 9のアプリケーションは動かなくなりますか? いいえ、引き続き動作します。ただし、Microsoftからのセキュリティ修正、バグ修正、技術サポートは提供されなくなります。 .NET Upgrade Assistantはまだサポートされていますか? いいえ。MicrosoftはGitHub Copilot upgrade agentに置き換える形で非推奨としました。後継はVisual Studio 2026とVisual Studio 2022 17.14.16以降に付属し、VS Code、Copilot CLI、GitHubでも利用できます。 .NET 10ではなく.NET 11を待つべきですか? いいえ。.NET 11はSTSリリースで、24か月ポリシーのもとでは.NET 10と同じ2028年11月ごろにサポートが終了する見込みです。.NET 10はすでに利用でき、より安全な移行先です。 HeroDevsは11月10日以降も.NET 9をサポートしますか? はい。NES for .NETは、.NET 6、.NET 8、.NET 9をカバーします。 11月10日の期限までにアップグレードが間に合わない場合 .NET 10への移行が2026年11月10日に間に合わないアプリケーションについては、NES for .NETが.NET 6、8、9にパッチを提供し続け、監査対応も維持します。その間に、慌てず適切に移行を進められます。保証範囲についてはHeroDevsにお問い合わせください(日本語で対応可能です)。 --- お問い合わせ 本記事の内容やHeroDevsのソリューション(NES等)について、日本語でのお問い合わせに対応しています。お気軽にHeroDevsお問い合わせページからご連絡ください。 --- 原文: herodevs.com (出典: herodevs.com)

  5. GitHub Copilot App のサンドボックスで .NET アプリを開発するための設定を試してみた GitHub Copilot App のローカルサンドボックスが GA したらしいので、.NET の開発で使えそうかどうか見てみようと思います。 今回は Windows 環境で、コンソールアプリの作成・実行と NuGet パッケージの追加を試し、その後に Minimal API も動かしてみました。 コンソールアプリは動かせましたが、ファイルのアクセス許可を調整したり、NuGet のエラーを調べたりする必要がありました。Minimal API は起動したものの、エンドポイントへのアクセスがタイムアウトし、今回はそこで断念しました。 ワークツリーの保存先を変更している場合の注意 GitHub Copilot App のワークツリーの保存先を D ドライブなどに変更している場合は、デフォルトの C ドライブ配下の場所に戻す必要があります。 現在、Windows のサンドボックスでは、システムドライブ以外にあるフォルダーを作業場所にすると、シェルでフォルダーの一覧取得などができない問題が報告されているためです。以下の Issue でも、D ドライブなどではアクセス拒否になり、システムドライブの C ドライブでは動くことが確認されています。 copilot-cli#5207 コンソールアプリを作成して実行するための設定 GitHub Copilot App にコンソールアプリの作成と実行を依頼したところ、dotnet new console の実行時にアクセス拒否のエラーが出ました。.NET SDK やテンプレートが使うフォルダーへの読み書きを許可する必要がありました。 使ったのは .NET 10 で、global.json で SDK を 10.0.403 に指定しています。 アクセスを拒否されたのは次のパスです。 %USERPROFILE%.dotnet\10.0.403.toolpath.sentinel %USERPROFILE%.templateengine\dotnetcli\10.0.403 %USERPROFILE%.templateengine\packages.json そこで、GitHub Copilot App のサイドバーから Settings を開き、Repositories で対象のリポジトリを選びます。Sandbox にある Additional read/write の Add folder から、次のフォルダーを追加しました。 C:\Users<ユーザー名>.dotnet C:\Users<ユーザー名>.templateengine <ユーザー名> は自分の環境に合わせて置き換えてください。 設定を変更しただけでは実行中のセッションに反映されないので、/restart-session でセッションを再起動する必要があります。 docs.github.com 上記のフォルダーへのアクセスを許可してセッションを再起動した後、Copilot に再実行を依頼すると、dotnet new console でのアプリ作成と、dotnet run での Hello, World! の表示に成功しました。 NuGet パッケージの追加を試してみる コンソールアプリの作成と実行ができたので、続いて Copilot に ReactiveProperty の追加を依頼しました。Copilot が実行したのは次のコマンドです。 dotnet add .\HelloWorld\HelloWorld.csproj package ReactiveProperty ところが、パッケージの追加もアクセス拒否で失敗しました。エラーメッセージには、拒否されたパスが出ていません。 error: Access to the path is denied. NuGet のパッケージ保存先やキャッシュのフォルダーが怪しいと思い、Additional read/write に次の4つを追加しました。 C:\Users<ユーザー名>.nuget C:\Users<ユーザー名>\AppData\Local\Temp\NuGetScratch C:\Users<ユーザー名>\AppData\Roaming\NuGet C:\Users<ユーザー名>\AppData\Local\NuGet 設定を反映して Copilot に再実行を依頼しましたが、それでも Access to the path is denied. が解消しませんでした。 ログを確認すると、次の URL からパッケージの登録情報を取得する GET リクエストには 200 OK が返っていました。少なくとも、この通信には成功しています。 api.nuget.org そこで、Copilot に NUGET_SHOW_STACK を有効にして再実行してもらいました。スタックトレースでは、NuGet.Protocol.HttpCacheUtility.CreateCacheFileAsync から呼ばれた System.IO.FileSystem.MoveFile で失敗していました。登録情報の取得ではなく、キャッシュファイルの移動で止まっていることが分かりました。 フォルダーの許可を追加しても解決せず、ログからもアクセスを拒否されたパスが分からなかったので、Process Monitor で実際のアクセス先を調べることにしました。 Process Monitor で失敗した操作を見る エラーメッセージだけでは先に進めなかったので、Microsoft の Process Monitor(Procmon)を使って、もう一度パッケージ追加を実行したときのファイル操作を確認しました。 learn.microsoft.com そこで見つかったのは、次の場所にあるファイルのリネームの失敗でした。ユーザー名やサンドボックスごとに変わる部分は置き換えています。 %LOCALAPPDATA%\Packages\sandbox.{GUID}\AC\NuGet\v3-cache<source-cache-dir>\list_reactiveproperty_index.dat-new list_reactiveproperty_index.dat-new の名前を、同じディレクトリ内で list_reactiveproperty_index.dat に変えようとしたところ、アクセスを拒否されていました。Procmon では、このリネーム操作(SetRenameInformationFile)の結果が ACCESS DENIED と記録されていました。 実際のアクセス先が AppData\Local\Packages 配下だったので、Additional read/write に次のパスを追加しました。 C:\Users<ユーザー名>\AppData\Local\Packages セッションを再起動して Copilot にパッケージ追加を再実行してもらうと、ReactiveProperty 9.10.0 と依存パッケージの導入に成功しました。値の変更を Subscribe で受け取り、コンソールに出力する処理も動きました。 これで動くようになりました。ただ、ここまでにいくつかのフォルダーを許可しているので、全部必要だったかは確認していません。AppData\Local\Packages を丸ごと許可するのは範囲が広いので、もう少し絞れないかは気になるところです。 私の環境でコンソールアプリを実行できた設定例 試した結果、ユーザー設定の Additional read/write(Folders the sandbox may read and modify)に残っていた .NET 用のパスは次の 7 件です。 C:\Users<ユーザー名>.dotnet C:\Users<ユーザー名>.templateengine C:\Users<ユーザー名>.nuget C:\Users<ユーザー名>\AppData\Local\Temp\NuGetScratch C:\Users<ユーザー名>\AppData\Roaming\NuGet C:\Users<ユーザー名>\AppData\Local\NuGet C:\Users<ユーザー名>\AppData\Local\Packages 設定する場合は、C:\Users<ユーザー名> の部分を自分の環境の絶対パスに置き換えてください。ここでは設定画面で環境変数が展開されるかどうかは確認していないので、絶対パスで記載しています。 これとは別に、添付画像へアクセスするために追加したパスもありました。 C:\Users<ユーザー名>.copilot\workspaces こちらは .NET の実行用ではなく、添付画像へのアクセス用です。 私の環境では、この設定でコンソールアプリの作成・パッケージ追加・実行までできました。もう少し許可するフォルダーを減らせるかもしれませんが、そこまでは試していません。 特に AppData\Local\Packages は、広い範囲の読み書きを許可することになります。今回の実験で使った設定であって、全員にそのまま追加することを勧めるものではありません。どこまで権限を絞っても動くかは未確認です。 Minimal API も試してみる コンソールアプリが動いたので、次は Copilot に Minimal API の作成と実行を依頼しました。アプリは起動しましたが、エンドポイントにアクセスするとタイムアウトしてしまいました。 サンドボックス設定の Outbound internet と Local network は、セッション開始時からどちらも ON にしていました。それでも接続できなかったので、ネットワーク周りの制約を調べてみました。 調べていると、Microsoft の MXC の公開資料で、似た症状の既知の制約を見つけました。Windows の特定の構成では、ホストからサンドボックス内で起動したサーバーへの接続がタイムアウトするというものです。 github.com/microsoft/mxc/blob/main/docs/backends/… リンク先では、Windows build 26691.1002 で、サンドボックスから外への通信をプロキシー経由に限定して試していました。ホストとのループバック通信を許可しても、ホストからサンドボックス内のサーバーへの接続はタイムアウトしたそうです。一方、プロキシーを使わない別の構成では接続できたとのことでした。 今回もこの制約に当たったのかは分かりません。ただ、起動した API に接続できない状態では開発を進められないので、今回はここまでにしました。 まとめ 今回は、サンドボックスのアクセス許可を追加することで、コンソールアプリの作成から NuGet パッケージの追加、実行までできました。ただ、途中で Procmon を使ってアクセス先を調べる必要があり、Minimal API も接続できないところで止まってしまいました。 今回試した Windows のローカル環境では、現時点で自分の実開発に使うにはまだ厳しいと感じました。サンドボックス自体は重要だと思っているので、今後の改善も追っていきたいです。

  6. Microsoft.UI.Reactorを学習する Microsoft.UI.Reactorとは Microsoft.UI.Reactor は、C#で WinUI アプリを宣言的に作る実験的なフレームワークです。 ※2026/11/01時点で 0.1.0-preview.16 版です。 試す プロジェクトを作成する winget install Microsoft.WinAppCli winapp new -t reactor -n Kashin777.UI.Reactor cd Kashin777.UI.Reactor 構成 !image.png csproj(抜粋) <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <!-- Windows GUI アプリとしてビルド --> <OutputType>WinExe</OutputType> <!-- .NET 10 と Windows SDK 10.0.26100.0 を対象にする --> <TargetFramework>net10.0-windows10.0.26100.0</TargetFramework> <!-- サポートする Windows の最低バージョン --> <TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion> <SupportedOSPlatformVersion>10.0.17763.0</SupportedOSPlatformVersion> <!-- WinUI アプリとしてビルドし、MSIX のビルド機能を有効にする --> <UseWinUI>true</UseWinUI> <EnableMsixTooling>true</EnableMsixTooling> <!-- C# の基本設定 --> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <!-- Windows アプリのビルドに必要なパッケージ --> <PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="*" /> <PackageReference Include="Microsoft.WindowsAppSDK" Version="*" /> <PackageReference Include="Microsoft.Windows.SDK.BuildTools.WinApp" Version="*" /> <!-- Microsoft.UI.Reactor --> <PackageReference Include="Microsoft.UI.Reactor" Version="0.1.0-preview.16" /> </ItemGroup> </Project> App.cs using Microsoft.UI.Reactor; using Microsoft.UI.Reactor.Core; using Microsoft.UI.Reactor.Layout; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using static Microsoft.UI.Reactor.Factories; // To learn more about Reactor, the Reactor project structure, and more about // our project templates, see: https://github.com/microsoft/microsoft-ui-reactor ReactorApp.Run<App>("Kashin777.UI.Reactor"); class App : Component { public override Element Render() { var titleBar = TitleBar("Kashin777.UI.Reactor") .Flex(shrink: 0); // This is the main content area of your application. // Add your UI elements here. var content = Border(Empty()).Flex(grow: 1, basis: 0); return FlexColumn(titleBar, content) .Backdrop(BackdropKind.Mica); } } とりあえず実行 dotnet run !image.png 画面を実装する 公式ドキュメントのCounter Example に従い、App.cs を修正してみます。 public override Element Render() { var titleBar = TitleBar("Kashin777.UI.Reactor") .Flex(shrink: 0); var (count, setCount) = UseState(0); // countプロパティとsetterを作成 var content = VStack(spacing: 12, // Vertical StackElement TextBlock($"Count: {count}").FontSize(20).SemiBold(), // element[0] TextBlock HStack(spacing : 8, // element[1] Horizontal StackElement Button("- 1", () => setCount(count - 1)), // 1デクリメント Button("Reset", () => setCount(0)), // リセット Button("+ 1", () => setCount(count + 1)) // 1インクリメント ) ).Padding(24); return FlexColumn(titleBar, content) .Backdrop(BackdropKind.Mica); } dotnet run !image.png 基礎 フック フック インタラクティブなUIには必ず状態が必要です。Reactorでは、状態はUseState時間とともに変化する値を管理するための主要なフックです。 コンポーネントは複数回呼び出すことができUseState、各呼び出しは独立した値を追跡します。 var (count, setCount) = UseState(0); var (firstName, setFirstName) = UseState(""); var (fontSize, setFontSize) = UseState(16.0); | フック | 戻り値 | 目的 | |--|--|--| | UseState | (T value, Action<T> set) | リアクティブな状態 — set 時に再レンダリングされます。 | | UseReducer | (T value, Action<Func<T,T>> update) または (TState, Action<TAction>) | 関数型または Redux スタイルの更新。 | | UseEffect | void | コミット後の副作用。Func<Action> オーバーロードを使用すると、次のエフェクトの実行前およびアンマウント時にクリーンアップが実行されます。 | | UseMemo | T | 計算結果のキャッシュ。依存項目のいずれかが不等となった場合に再実行されます。 | | UseRef | Ref<T>(mutable .Current 付き) | 変更時でも再レンダリングを行わずに、レンダリング間を通じて状態を保持します。 | | UseCallback | Action | レンダリング間を通じて安定したデリゲート識別子。 | | UseContext | T | 周囲の Context 値を読み取ります。 | | UseObservable | T | 追跡対象の INotifyPropertyChanged ソースが変更を発生させた際に再レンダリングを行います。 | | UseExternalStore | TSnapshot | subscribe/getSnapshot ストアを Reactor にブリッジし、スナップショットが変更された場合にのみ再レンダリングします。 | | UseResource | AsyncValue<T> | キャッシュされた非同期読み取り(「非同期リソース」を参照)。 | | UsePersisted | (T, Action<T>) | プロセス内のアンマウント/リマウント後も存続する UseState — メモリ内、終了時にクリアされます(「永続性」を参照)。 | レイアウト レイアウト | 要素 | 目的 | |--|--| | VStack | 縦積み(上から下へ子要素を配置) | HStack | 水平スタック(左から右へ) | Grid | 行/列グリッド(比例サイズ) | ScrollView | オーバーフローコンテンツ用のスクロール可能なラッパー | Border | 背景、角丸、ストローク付きコンテナ コントロール コントロールカタログ | カテゴリ | 中身は? | |--|--| | フォーム | テキスト入力、ピッカー、ボタン、検証プリミティブ | | コレクション | リスト、グリッド、仮想化リスト、リピーター | | テキストとメディア | 見出し、リッチテキスト、画像、メディアプレーヤー | | ステータスと情報 | 進捗状況、情報バー、バッジ、指導のヒント | | レイアウトとコンテナ | スタック、グリッド、境界線、スクロールホスト、ペイン | | ナビゲーション | ナビゲーションビュー、フレーム、タブ、パンくずリスト、ピボット | | 図形とアイコン | 長方形、楕円、線、パス、アイコンのソース | | ダイアログとフライアウト | コンテンツダイアログ、メニューフライアウト、コマンドバーフライアウト | | データシステム | DataGrid、列、データソース、ページング | | チャート作成 | 線グラフ、棒グラフ、面積グラフ、円グラフ、力グラフ | ホットリロード ホットリード dotnet watch run アプリを起動したまま、ボタンのラベルを変更して保存したら PS C:\Users\Kashin777\source2\repos\Kashin777.UI.Reactor> dotnet watch run dotnet watch 🔥 Hot reload enabled. For a list of supported edits, see https://aka.ms/dotnet/hot-reload. dotnet watch 💡 Press Ctrl+R to restart. 復元が完了しました (0.0 秒) 0.1 秒後に 成功しました をビルド info NETSDK1057: プレビュー版の .NET を使用しています。https://aka.ms/dotnet-support-policy をご覧ください Kashin777.UI.Reactor net10.0-windows10.0.26100.0 win-x64 成功しました (0.4秒) → bin\Debug\net10.0-windows10.0.26100.0\win-x64\Kashin777.UI.Reactor.dll 0.5 秒後に 成功しました をビルド dotnet watch ⌚ Loading projects ... dotnet watch ⌚ Loaded 1 project(s) in 0.5s. C:\Users\Kashin777\source2\repos\Kashin777.UI.Reactor\Properties\launchSettings.json からの起動設定を使用中... ⠼ Launching packaged application... ✅ 43A37F59-B43C-4C5A-9E09-1DE873E18ECA_1z32rh13vfry6 launched (PID: 22536) dotnet watch ⌚ File updated: .\App.cs dotnet watch ⚠ [Kashin777.UI.Reactor (net10.0-windows10.0.26100.0)] Further changes won't be applied to this process. ドキュメントに従い dotnet watch run で起動したのですが、App.cs の変更は検知されるもののリロードされず...

  7. JSX が JavaScript になるまで React のコンポーネントには、こんなコードを書きます。 return <h1 className="title">Hello, {name}!</h1>; 見た目はほとんど HTML です。でも、よく見ると HTML ではありません。React の JSX では、属性は class ではなく className ですし、{name} のように JavaScript の式がそのまま埋め込まれています。かといって、JavaScript にも return の後ろにタグを書く構文はありません。 では、ブラウザはこのタグを HTML として読んでいるのでしょうか。それとも JavaScript として読んでいるのでしょうか。 答えはどちらでもありません。ブラウザに届く時点で、このタグはもう残っていないからです。筆者も「ビルドのときに何かに変換されている」ことは知っていました。ただ、何に変換されて、ブラウザが最終的に何を受け取っているのかは説明できませんでした。この記事では、変換の途中でできるもの(中間生成物)を 1 つずつ取り出しながら、.jsx に書いたタグが JavaScript になり、実行されて何を返すのかまでを追いかけます。 この記事の前提 環境: React 19.3.1 / react-dom 19.3.1 / Node.js v26.12.1 / macOS ブラウザでの確認: Vite 8.3.5(@vitejs/plugin-react 6.1.2)/ Google Chrome 156.0.8078.80 変換ツール: Babel(@babel/core 8.0.9・@babel/preset-react 8.0.1・@babel/parser 8.0.8)を主に使い、比較用に TypeScript 7.0.2 の tsc / SWC(@swc/core 1.16.20)/ esbuild 0.28.2 / Oxc(oxc-transform 0.156.0)も使います。TSX のコラムでは、ほかに @babel/preset-typescript 8.0.7・@babel/plugin-syntax-typescript 8.0.3・@types/react 19.3.0 を使います 対象: React の標準の変換方式(automatic runtime)。断りがない限り、開発用の出力(development)はオフにした結果を載せています 題材: 小さなコンポーネントを書いた App.jsx が中心です。TypeScript(.tsx)の場合に何が変わるかは、末尾のコラムで扱います 範囲外: 変換後のオブジェクトが Fiber になり DOM に反映される過程(reconcile)、Hooks の実装、Server Components 記事中のログ・エラーメッセージ・出力は、すべて筆者が上記環境で実際に採取したものです。AST のダンプと 5 つのツールの比較は、それぞれのツールを Node.js から呼ぶ小さなスクリプトによるものです 全体像 パーサー — JSX を構文として読める。ソースを AST(構文木)にし、タグを JSXElement などのノードとして表す。各変換ツールが内蔵している(Babel なら @babel/parser) 変換 — AST の JSX のノードを関数呼び出し(_jsx(...))に書き換え、呼び出し先の import を差し込む。Babel・SWC・esbuild・Oxc・tsc などが担う ランタイム(react/jsx-runtime) — 変換後の _jsx(...) の呼び出し先。React Element と呼ばれるただのオブジェクトを返す レンダラー(react-dom) — React Element を受け取り、ブラウザでは DOM を組み立てる(サーバーでは HTML 文字列にもできる)。この記事では中身には踏み込まない ブラウザが受け取っているのは、タグが関数呼び出しに置き換わった普通の JavaScript です。 その JavaScript を実行したあと、react-dom が DOM を組み立てます。 どの関数をどの形で呼ぶかは、JSX の構文自体には決まっていません。React の automatic runtime では、呼ぶのは react/jsx-runtime の jsx(type, props, key) で、この形は React が定めた約束です。変換ツールは、呼び出し先の設定(importSource など)で指定された先に向けて、この約束どおりに書き換えます。そのため、どの変換ツールを使っても、ほぼ同じ JavaScript になります。 課題 — React を書いていて浮かぶ疑問 冒頭の疑問ともう 1 つ、次の 2 つに答えます。 ブラウザは JSX のタグを HTML として読んでいるのか、JavaScript として読んでいるのか JavaScript はスクリプト言語で、書いたファイルをそのまま渡せば動くはずなのに、なぜ React のプロジェクトはデプロイの前にビルドが要るのか 題材は、Fragment(<>)・属性・埋め込みの式・イベントハンドラ・key が一通り入った小さなコンポーネントです。 // App.jsx import { useState } from "react"; export function App({ name }) { const [count, setCount] = useState(0); return ( <> <h1 className="title">Hello, {name}!</h1> <button onClick={() => setCount(count + 1)}> count is {count} </button> {[1, 2].map((n) => <li key={n}>{n}</li>)} </> ); } 試したこと — 中間生成物を段階ごとに取り出す 段階 0: JavaScript のエンジンは JSX を読めない まず、変換をせずにそのまま実行してみます。JSX を含むファイルを .mjs として Node.js に渡しました。 $ node stage0/hello.mjs const el = <h1>hi</h1>; ^ SyntaxError: Unexpected token '<' タグの 1 文字目 < で構文エラーです。拡張子を .jsx にした場合は、プロジェクトの設定で結果が変わりました。package.json が "type": "module" なら構文を読む前に ERR_UNKNOWN_FILE_EXTENSION で弾かれ、CommonJS なら .js として読まれて同じ SyntaxError になります。 変換をしない静的なサーバーから、次の HTML を Chrome で開きました。 <script type="module"> const el = <h1>hi</h1>; </script> コンソールには、Node.js と同じエラーが出ました。 SyntaxError: Unexpected token '<' JSX は ECMAScript(JavaScript の標準仕様)には入っていない構文拡張です。JSX 自体の仕様の草案(react/jsx、旧 facebook/jsx)も、エンジンやブラウザが実装することは想定していないと冒頭で断っていて、何に変換されるかも定めていません。つまり、ブラウザは JSX を HTML としても JavaScript としても読めません。JSX は、ブラウザに届く前に必ず誰かが JavaScript に変換している構文です。1 つ目の疑問への答えの半分がこれです。 2 つ目の疑問「なぜビルドが要るのか」の答えの中心も、ここにあります。ブラウザに渡す前に JSX を JavaScript へ変換する工程が要り、それを担っているのがビルドです。開発中に同様の変換をしているのは開発サーバーで、その様子は段階 2 の最後で見ます。 段階 1: パーサー — タグは JSX 専用のノードになる 最初の仕事は、JSX を読めるパーサーで AST を作ることです。Babel のパーサー(@babel/parser に jsx プラグインを付けたもの)で、return (...) の中身をダンプしました。長いので <h1> と <button> の部分を抜きます。 JSXFragment JSXOpeningFragment JSXText "\n " JSXElement JSXOpeningElement JSXIdentifier "h1" JSXAttribute JSXIdentifier "className" StringLiteral "title" JSXText "Hello, " JSXExpressionContainer Identifier "name" JSXText "!" JSXClosingElement JSXIdentifier "h1" JSXText "\n " JSXElement JSXOpeningElement JSXIdentifier "button" JSXAttribute JSXIdentifier "onClick" JSXExpressionContainer ArrowFunctionExpression (略) JSXText "\n count is " JSXExpressionContainer Identifier "count" JSXText "\n " JSXClosingElement JSXIdentifier "button" (以下 map の JSXExpressionContainer) 普通の JavaScript の AST には無い、JSX で始まるノードが並んでいます。タグ名の h1 も、JavaScript の識別子を表す Identifier ではなく、JSXIdentifier という別の種類のノードです。大文字・小文字・ドット付きのタグを並べたファイルでも確かめました。 // Main.jsx import { App } from "./App.jsx"; export const page = <App name="World" />; export const tag = <app name="World" />; export const member = <ui.Button />; --- page JSXElement JSXOpeningElement JSXIdentifier "App" JSXAttribute JSXIdentifier "name" StringLiteral "World" --- tag JSXElement JSXOpeningElement JSXIdentifier "app" (略) --- member JSXElement JSXOpeningElement JSXMemberExpression JSXIdentifier "ui" JSXIdentifier "Button" Babel のパーサーでは、大文字の App も小文字の app も同じ JSXIdentifier でした。この時点ではまだ「HTML の要素か、自作のコンポーネントか」を区別していません(Oxc のように、パースの時点で区別するパーサーもあります)。 段階 2: 変換 — JSX が関数呼び出しになる App.jsx を Babel(@babel/preset-react、automatic runtime)で変換し、dist-jsx/App.js に書き出しました。 import { useState } from "react"; import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime"; export function App({ name }) { const [count, setCount] = useState(0); return /#PURE/_jsxs(_Fragment, { children: [/#PURE/_jsxs("h1", { className: "title", children: ["Hello, ", name, "!"] }), /#PURE/_jsxs("button", { onClick: () => setCount(count + 1), children: ["count is ", count] }), [1, 2].map(n => /#PURE/_jsx("li", { children: n }, n))] }); } タグが _jsxs("h1", { className: "title", children: [...] }) という関数呼び出しに書き換わりました。 2 行目の import は、ソースには書いていません。呼び出す関数(react/jsx-runtime の jsx / jsxs)がどこから来るかを書かないと動かないので、変換ツールが自分で差し込んだものです。_jsx は、その jsx を別名で import したものです。/#PURE/ は「戻り値を使っていなければ消してよい」というバンドラ向けの注釈(PURE 注釈)です。 出力には、ほかにも決まりがあります。 属性と子は 1 つのオブジェクト(props)にまとめられ、子は props.children に入る 改行を含む空白だけのテキストを除いて、ソースに書いた子が複数なら _jsxs、1 つ以下なら _jsx になる key は props から外れて第 3 引数になる(_jsx("li", { children: n }, n)。例外もありますが、ここでは扱いません) 大文字のタグは変数、小文字のタグは文字列 Babel のパーサーでは区別されていなかった大文字と小文字は、変換の段階で分かれます。Main.jsx の変換結果です。 import { App } from "./App.jsx"; import { jsx as _jsx } from "react/jsx-runtime"; export const page = /#PURE/_jsx(App, { name: "World" }); export const tag = /#PURE/_jsx("app", { name: "World" }); export const member = /#PURE/_jsx(ui.Button, {}); 大文字で始まる App は変数 App の参照に、小文字の app は文字列 "app" に、ドット付きの ui.Button はプロパティの参照になりました。コンポーネント名を大文字で始めなければいけないのは、このルールで HTML の要素名(文字列)と区別されるからです。 5 つのツールで変換して比べる 実際のプロジェクトで JSX を変換しているのは、Babel だけではありません。Next.js は既定で SWC を使い、Vite 8 では Vite 本体の Oxc が JSX を変換していて、@vitejs/plugin-react v6 は Babel への依存をなくしました。そこで、同じ App.jsx を Babel・SWC・esbuild・Oxc・tsc の 5 つで変換しました。設定は 3 つそろえています。automatic runtime、importSource は react、開発用の出力(development)はオフです。 生の出力は見た目がかなり違います。たとえば esbuild はこうです。 import { Fragment, jsx, jsxs } from "react/jsx-runtime"; import { useState } from "react"; function App({ name }) { const [count, setCount] = useState(0); return /* @PURE */ jsxs(Fragment, { children: [ /* @PURE */ jsxs("h1", { className: "title", children: [ "Hello, ", name, "!" ] }), /* @PURE */ jsxs("button", { onClick: () => setCount(count + 1), children: [ "count is ", count ] }), [1, 2].map((n) => /* @PURE */ jsx("li", { children: n }, n)) ] }); } export { App }; import の順番、_jsx か jsx かという名前、PURE 注釈の有無と書き方、整形、export の形がツールごとに違います。そこで import 文と PURE 注釈を消し、名前の先頭の _ と export の形をそろえ、整形し直してから比べるスクリプトを書きました。消した import 文も、import 元は 5 つとも react/jsx-runtime で、違うのは並び順と別名だけでした。 App: 1 distinct normalized output(s) [tsc, babel, swc, esbuild, oxc] function App({name}){const[count,setCount]=useState(0);return jsxs(Fragment,{children:[jsxs("h1",{className:"title",children:["Hello, ",name,"!"]}),jsxs("button",{onClick:()=>setCount(count+1),children:["count is ",count]}),[1,2].map(n=>jsx("li",{children:n},n))]})} 5 つの出力は、書き方の差を除くと完全に一致しました。Main.jsx でも同じで、5 つのツールすべてが大文字のタグを変数、小文字のタグを文字列に分けていました。ui はどこにも定義していませんが、どのツールもそのまま変換しています。変換ツールは、名前の正体を調べていません。 実装は 5 つともまったく別物で、言語も JavaScript(Babel)・Rust(SWC・Oxc)・Go(esbuild・tsc)とバラバラです。それでも出力がそろうのは、関数の形(jsx(type, props, key))と、そこへの渡し方(子は props.children に、key は第 3 引数に、子が複数なら jsxs)までが React の決めた約束で、どのツールもそれに合わせて書き換えているからです。変換ツールはその約束どおりに呼び出しを書けばよく、他のファイルを見る必要がありません。 なお、開発用の出力をオンにすると、同じ正規化でも 4 通りに分かれました。tsc・SWC・esbuild・Oxc はデバッグ用のソースの位置(ファイル名・行・列)を同じ値で渡しますが、ファイル名を変数に入れるか(tsc は const、Oxc は var)直接書くか(SWC・esbuild)が違い、Babel 8 は位置の情報そのものを渡しません。 ブラウザに届く JavaScript を確かめる この形のままブラウザに届くことを、実際のプロジェクトでも確かめました。同じ App.jsx を Vite 8 のプロジェクトに置き、vite build の出力から App の部分を抜き出しました。Vite 8 の変換は、先ほどの 5 つのうちの Oxc です。 return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(h1,{className:title,children:[Hello, ,e,!]}),(0,p.jsxs)(button,{onClick:()=>n(t+1),children:[count is ,t]}),[1,2].map(e=>(0,p.jsx)(li,{children:e},e))]}) minify(圧縮)で変数名が縮み、文字列の引用符もバッククォートになっています。p はバンドルに取り込まれた react/jsx-runtime を指す変数で、(0,p.jsxs)(...) は this を渡さずに p.jsxs を呼ぶための、バンドラの書き方です。形は Babel の出力と同じ jsxs("h1", { className: "title", children: [...] }) で、出力の中に <h1 という文字列は 1 つもありませんでした。 開発サーバー(vite)でも確かめました。Chrome が App.jsx を要求すると、Content-Type: text/javascript の JavaScript が返ってきます。ブラウザはモジュールとして読み込むファイルの種類を拡張子ではなく Content-Type で判断するので、名前が .jsx のままでも JavaScript として実行します。中身は開発用の _jsxDEV(...)(react/jsx-dev-runtime)の呼び出しでしたが、タグが残っていない点は同じでした。あわせて、import { useState } from "react" も、/node_modules/.vite/deps/react.js?v=… からの import と const useState = …["useState"] という形に書き換わっていました。react の npm パッケージは CommonJS で配布されていてブラウザではそのまま動かないので、Vite が事前に ESM へ変換しておいたファイルです。 ブラウザに届いているのは、タグが消えた関数呼び出しの JavaScript でした。これが 1 つ目の疑問の残り半分の答えです。 段階 3: ランタイム — jsx() はただのオブジェクトを返す では、jsx() は何を返すのでしょうか。変換後の App.js と同じ呼び方で react/jsx-runtime の jsx / jsxs を呼び、戻り値を出力しました(jsx は本来アプリから直接呼ぶ関数ではなく、ここでは観察のために呼んでいます。NODE_ENV=production での結果です)。 --- jsxs("h1", ...) { '$$typeof': Symbol(react.transitional.element), type: 'h1', key: null, ref: null, props: { className: 'title', children: [ 'Hello, ', 'World', '!' ] } } 返ってきたのは、ただのオブジェクトでした。これが React Element です。type にはタグ名の文字列 'h1'、props には属性と子がそのまま入っています。$$typeof の値 Symbol(react.transitional.element) は、このオブジェクトが React Element であることを示す印です。段階 2 で JSX は関数呼び出しになりましたが、その関数がやっているのは「この形のオブジェクトを作る」ことだけです。DOM の要素はまだどこにも作られていません。 コンポーネントでも同じです。App を、呼び出された回数を数える関数 Counted で包んで jsx() に渡すと、type に関数そのものが入ったオブジェクトが返ります。 --- jsx(Counted, { name }) { '$$typeof': Symbol(react.transitional.element), type: [Function: Counted], key: null, ref: null, props: { name: 'World' } } type is the function itself: true | component called: 0 この時点で Counted は 1 回も呼ばれていませんでした。<App /> と書いても、App() が実行されるわけではありません。「App という関数を、この props で呼んでほしい」と書いたオブジェクトができるだけです。いつ呼ぶか(呼ばないか)はレンダラーが決めます。 結果 最後に、Vite の開発サーバーで開いた Chrome のページで、react-dom が組み立てた DOM を見ました。ページ上で document.getElementById("root").innerHTML を評価し、#root の中身を文字列にして取り出したものです。 <h1 class="title">Hello, World!</h1><button>count is 0</button><li>1</li><li>2</li> ここで初めて、画面の要素(DOM)が出てきました。ブラウザでは HTML の文字列を作って流し込んでいるのではなく、react-dom が React Element をもとに DOM を直接組み立てています。className は DOM では class 属性になっています。className は DOM の要素が持つプロパティ名(element.className)に合わせた名前で、class 属性として反映するのはレンダラーの仕事です。 ここまでをまとめると、次のとおりです。 JSX は ECMAScript の構文ではなく、Node.js も Chrome もタグの 1 文字目で SyntaxError を出した(段階 0) Babel のパーサーは、タグを JSXElement・JSXText などのノードにした。大文字のタグも小文字のタグも同じ JSXIdentifier だった(段階 1) JSX は _jsx / _jsxs の呼び出しになり、呼び出し先(react/jsx-runtime)の import が自動で差し込まれた。大文字のタグは変数、小文字のタグは文字列になり、key は props から外れて第 3 引数になった(段階 2) 設定をそろえた 5 つの変換ツールの出力は、書き方の差を除いて一致した(段階 2) Vite のビルド出力にも開発サーバーの応答にも、タグは残っていなかった(段階 2) jsx() は $$typeof・type・key・ref・props を持つただのオブジェクトを返し、コンポーネント関数はこの時点で呼ばれていなかった(段階 3) DOM を組み立てるのは react-dom で、className は class 属性になった 学び JSX の変換は、設定が分かればファイル 1 枚で完結する。 呼び出し先(react/jsx-runtime)と呼び出しの形(jsx(type, props, key))がファイルの外で決まっているので、変換ツールは他のファイルを見ずに書き換えられる。だから開発サーバーは、ブラウザに要求されたファイルだけをその場で変換して返せる 変換後の JSX を実行すると、「何を描画してほしいか」を書いたただのオブジェクトができる。 コンポーネントを呼ぶのも DOM を作るのも、そのオブジェクトを受け取ったレンダラーの仕事 課題に挙げた 2 つの疑問に答えると、こうなります。 「ブラウザは JSX を HTML として読んでいるのか、JavaScript として読んでいるのか」 — タグのままでは、HTML としても JavaScript としても読めません(段階 0)。タグはブラウザに届く前に関数呼び出しへ置き換わっていて、ブラウザはそれを普通の JavaScript として実行します。画面の要素(DOM)は、その実行の結果としてレンダラーが組み立てたものです。 「なぜスクリプト言語の JavaScript なのにビルドが要るのか」 — 書いたファイルが、ブラウザがそのまま実行できる形になっていないからです。その代表が JSX で、JavaScript ではありません。開発サーバーは JSX だけでなく、from "react" のような名前だけの import も、CommonJS で配布されている react を ESM に変換したファイルの URL に書き換えていました。開発中はこの書き換えを開発サーバーがその場でしてくれますが、静的ファイルを配るだけのデプロイ先には、それをしてくれる仕組みがありません。だから、デプロイ前のビルドで済ませておきます。 JSX の挙動で迷ったときは、DevTools の Network タブで届いた App.jsx を開くなどして、変換後の JavaScript を一度のぞいてみるところから始めていきたいですね。 コラム: TSX の場合 — tsx → jsx → js なのか、tsx → ts → js なのか ここまでは .jsx で見てきましたが、TypeScript と組み合わせて .tsx で書くプロジェクトも多くあります。.tsx には型と JSX の 2 つが入っているので、JavaScript になるまでに「型を消す」と「JSX を変換する」の 2 つの変換が要ります。題材の App.tsx は、App.jsx に型を 2 か所足しただけのものです。 type Props = { name: string }; export function App({ name }: Props) { // (以下 App.jsx と同じ) 結論から言うと、どちらの順でもできて、結果は同じでした。automatic runtime では、2 つの変換は互いに独立しているからです(classic runtime では、型を消すときに使われていない import を消す処理が import React を消してしまうことがあり、完全には独立していません)。 まず tsx → jsx → js です。tsc の jsx: preserve は、App.tsx から型を消し、JSX は残したまま App.jsx を出します。 // tsc --jsx preserve の出力(App.jsx) export function App({ name }) { const [count, setCount] = useState(0); return (<> <h1 className="title">Hello, {name}!</h1> (略) これを Babel で変換すれば JavaScript になります。 もう一方の順番の tsx → ts → js も作れます。Babel に TypeScript の構文プラグイン(@babel/plugin-syntax-typescript。構文を読むだけで、型は消さない)を付けて JSX の変換をかけると、型が残ったまま JSX が関数呼び出しになりました。 // Babel(preset-react + TypeScript の構文プラグイン)の出力。型はまだ残っている type Props = { name: string; }; export function App({ name }: Props) { const [count, setCount] = useState(0); return /#PURE/_jsxs(_Fragment, { (略) これを esbuild で型を消して JavaScript にしました。2 つの経路の最終出力を、本文と同じスクリプトで直接変換の結果と比べると、すべて一致しました(出力の見出しは読みやすく書き換えています)。 App: 1 distinct normalized output(s) [直接(tsc), 直接(babel), tsx→ts→js, tsx→jsx→js, 直接(oxc)] TypeScript 7 の実装(typescript-go の typescript/v7.0.2 タグの internal/compiler/emitter.go)で、tsc の変換器(tsc の中で 1 つの変換を受け持つ部品)を並べている getScriptTransformers を見ると、型を消す変換器が先で、JSX の変換器が後でした。 // transform TypeScript syntax { // (中略) // erase types tx = append(tx, tstransforms.NewTypeEraserTransformer(&opts)) // (中略) } if jsxTransformEnabled { tx = append(tx, jsxtransforms.NewJSXTransformer(&opts)) } つまり tsc は tsx → jsx → js の順で、jsx: preserve は、この並びから JSX の変換器だけを外した姿です。ただし中間のファイルはできず、どの変換器も前の変換器が返した AST を受け取り、次の AST を返していくだけです。他のツールも中間のファイルは作りませんが、作りはツールごとに違います。たとえば esbuild は型注釈をパースの時点で読み飛ばすので、そもそも型が AST に残りません。 .tsx で差が出るのは、変換の順番よりも、パーサーの読み方と型検査のほうです。tsc は型を検査するために、import を辿ってコンパイル対象のファイル一式(Program)を集め、名前の正体を解決し、型を計算します。 .tsx という拡張子は、TypeScript のパーサーの読み方を切り替える。.ts では型アサーションとして通る <string>v が、.tsx では TS17008: JSX element 'string' has no corresponding closing tag になった。.tsx でジェネリックなアロー関数を <T,>(x: T) => x とカンマ付きで書くのはこのため tsc --traceResolution で見ると、ソースのどこにも書いていない react/jsx-runtime が、react より先に解決されていた。JSX の型を引くため tsc は @types/react の JSX 名前空間で JSX を検査する。h1 は JSX.IntrinsicElements という interface のプロパティとして解決され、className は HTMLAttributes のプロパティだった。class と書くと TS2322 … Property 'class' does not exist … Did you mean 'className'? になる(それでも JavaScript は出力される) 所要時間は全体で約 0.18 秒で、そのうち Check(型検査の工程)が約 0.16 秒、JSX の変換を含む書き出し(Emit)は 0.001 秒だった。--noCheck を付けると全体で 0.020 秒になる。React を含まない 1 行の .ts と比べると、React の型定義(@types/react の 3 ファイルと csstype)が Program に加わった分、計算された型の数が約 2 倍になっていた。この題材は skipLibCheck を付けていないので、増えた分のほとんどは JSX ではなく型定義ファイル自体の検査だ 変換はファイル 1 枚で終わるのに、検査は呼び出し先の型定義まで Program を広げないとできません。.tsx の JSX は、この 2 つの仕事の重さの差がはっきり見える場所でした。 コラム: React 以外の JSX JSX は Preact・Hono・Vue・Solid でも書けます。構文と AST(段階 0・1)はどのフレームワークでも共通で、違いが出るのは「何の関数を呼ぶか」(段階 2)と「その関数が何を返すか」(段階 3)です。 ! 以下は各フレームワークのドキュメントに基づく整理で、この記事では検証していません。 フレームワーク 変換のしかた(呼び出し先) 返すもの React react/jsx-runtime React Element(ただのオブジェクト) Preact preact/jsx-runtime VNode Hono hono/jsx/jsx-runtime HTML 文字列にできるノード Vue 3 専用の Babel プラグインが生成する関数呼び出し VNode Solid 専用のコンパイラが生成する DOM 操作のコード 実際の DOM ノード(ブラウザ向けの出力) React・Preact・Hono は、jsx-runtime という同じ形の約束の上で返すものだけを差し替えているので、変換ツールの呼び出し先の設定(importSource)を変えるだけで切り替わります。Vue にも vue/jsx-runtime はありますが、公式が案内しているのは専用の Babel プラグインです。Solid はこの約束を使わず、JSX を、DOM を直接組み立てるコードにコンパイルします。 参考 JSX の仕様草案: react.github.io React「Writing Markup with JSX」(className の由来): react.dev React ブログ「Introducing the New JSX Transform」(automatic runtime): legacy.reactjs.org Next.js Compiler(SWC): nextjs.org @vitejs/plugin-react の CHANGELOG(v6 で Babel への依存を削除): github.com/vitejs/vite-plugin-react/blob/main/pac… Oxc: oxc-project/oxc esbuild の設計(型注釈の読み飛ばし): github.com/evanw/esbuild/blob/main/docs/architect… typescript-go internal/compiler/emitter.go(v7.0.2): github.com/microsoft/typescript-go/blob/typescrip… Preact: preactjs.com Hono の JSX: hono.dev Vue「Render Functions & JSX」: vuejs.org Solid の JSX コンパイラ(dom-expressions): ryansolid/dom-expressions

  8. u know i completely forgot i ever wrote this comment. what the hell TypeScript#33304

    6 likes
  9. Would love everyone's opinion on microsoft/WindowsDeveloperConfig

    82 likes · 8 reposts · 6,675 views
  10. Reverse Engineering Block Blast Block Blast looks like a puzzle game. A decompile of the app suggests it's closer to a per-player ad pricing engine with a puzzle attached. Three tree-based models run on your phone, a bandit experiment tunes when you lose, and a rule decides your next three pieces based on what ad is sitting in memory. The Problem It's Solving The game is free and has no ad-free purchase, so revenue depends on rewarded and full-screen ads. Sensor Tower estimates put its ad revenue at roughly $127 million for January to May 2026, ahead of Candy Crush Saga at $81.1 million. Ad value varies a lot per player (country, device, history), and the best moment to show a rewarded ad is right after a loss. Making that work needs per-player prediction, per-deal control of the pieces, and the ability to change both without shipping an app update. How the System Is Built The research is Ayo Omolewa's breakdown of Android 10.8.2 and iOS 7.4.9, using jadx and Ghidra. The store APK holds very little. Logic ships as "traits" (modules with variants called arms), and at launch the server tells the app which arm of which trait you get. His config named about 700 traits, selected 254, and 101 were fetched after install as XXTEA-encrypted, Brotli-compressed JavaScript. Two players can run different games, and the studio can change yours silently. The Models | Model | Size and inputs | What it decides | |---|---|---| | XGBoost regression (xgboost_regression_model111.json) | 59 trees, depth up to 8, 27 inputs (18 about ads) | finalEcpm: your estimated ad value | | XGBoost classifier (predict_travel_difficulty_dead) | 500 trees, 52 inputs | Where in a level the lethal puzzle lands | | LightGBM | 1,000 trees, 93 inputs | Whether you'll be less active tomorrow | The ad value model. The inputs are mostly money-related: prices of ads loaded today and yesterday, country, phone model, RAM, install date, and how your first game went. The trees lean hardest on first score, latest ad price, RAM, phone model and country. The inference code is a plain loop: start each tree at the root, go left or right on a feature threshold (missing values follow a default direction), add the leaf weight to a running sum starting at the base score. Omolewa's port reproduces the game's outputs to the last decimal. Changing one input on a made-up US player on an iPhone 15 gives: | Change | Ad value (eCPM) | |---|---| | Baseline (US, first score 1,000) | 25.48 | | Brazil | 8.08 | | India | 5.59 | | First score 500 / 2,000 / 10,000 | 25.79 / 21.12 / 20.34 | The same US baseline on Android scores 48.96. The output feeds other rules. One compares your rewarded and full-screen prices and, if rewarded is worth at least twice full-screen in the shipped version, grants an extra revive (which plays a rewarded ad). Others add a full-screen ad when your price is high or skip full-screen ads when you're worth almost nothing. The "where do you lose" model. The game scores 12 candidate options (4 values of a sw_process setting times 3 difficulty levels) and keeps the argmax. Inputs are mostly about your history: current level, attempts, games finished this week, time since install. The winning sw_process maps to a stretch of the level (first 30%, 30 to 80%, last 20%). On reaching it, players who usually accept revives (above 75%) get an extra one, and from the fourth deal after that the game requests the lethal puzzle. Other rules read the same pick the opposite way and make the level easier when it lands on the fourth option. The churn model. If the LightGBM score is 0.69 or higher, a pink revive button replaces the normal one and skips the ad, once a day. It leans on app age, high score, RAM and average score. Server-side models. Rules also call models named for churn, LTV, revive-click and xDeepFM. Those weights never reach the phone, so the only visible part is the request. One call to /v1/ecpm_prediction sends 40 fields, including carrier, storage, hour of day and recent ad prices. The Rules That Act on the Predictions These are hand-written, not learned. RewardHighValueAdHarvestTrait fires when you finished your last three rewarded ads, the ad currently loaded is worth at least 3.5 times your last one (read from AppLovin MAX eCPM), and you're 1,000 points past your high score (500 or 750 in other arms). It then requests generator ZHI_SI_TI. The generator picks two pieces that fit and one that doesn't, searches every order and placement including line clears, and keeps the set only if nothing works. The code labels the pieces "lethal puzzle" in Chinese. PersonalMarginBreakTrait gives every deal a 20% chance of the same hand once you're 10% past your record. MultiClearBoostThenKillTrait sends your user ID to two server endpoints, and for the tiers labelled "not sensitive to being forced to die," waits for a big clear, then requests the lethal puzzle a few rounds later once the game reaches roughly your usual length. FastHandPunishTrait asks for hard pieces when your last six sets averaged under 4.2 seconds and you're past 93% of your high score. MaturityDevelopmentV2Trait scores habit, skill and ad history (10.98, 14.66 and 19.27 in the live test), and when the total (44.91) is under 65 it swaps hard puzzles for easy fills. AdPlusMinusStrategyTrait adds a random bonus of up to 10% of your high score after one type of revive. MABXiBaiTrait is a six-arm experiment on how soon the lethal puzzle may be requested: never, or after 4, 6, 10, about 17 or 30 minutes. Per arm it logs whether you started a new game within 15 minutes and the share of revive offers you accepted. Why This Is a Bigger Deal Than It Looks The ML itself is cheap: tree ensembles walked in a loop over JSON, no GPU, runs on a low-end phone and offline. The engineering is the delivery layer. Server-assigned arms, encrypted hot-loaded JavaScript and per-player A/B tests make this a feature-flag platform with bandit tuning, which is why it can be changed daily. Because the lethal-puzzle rule needs a rewarded ad loaded, it can't fire offline or with a phone-wide DNS blocker, while ad-independent rules keep running. Apple permits JavaScript updates that don't change what the app is. Whether this qualifies is Apple's call. The usual caveat applies: this is one researcher's analysis. mobilegamer.biz reported no reply from Hungry Studio, and TechRadar noted that independent verification matters. The evidence bundles (decoded rules, test scripts, hashes) are public at Ayoships if you want to run the checks yourself. Availability and Access The game is on Google Play and iOS. The decryption key and the steps for getting past the apps' protection aren't published. If a free puzzle game ships three on-device models and a bandit experiment, the real question for developers isn't whether consumer apps use ML. It's how much of their behavior now lives in a config server instead of the binary. Follow for more coverage on MCP, agentic AI, and AI infrastructure. Inspired to write this by @StompnWorldfan's video on YouTube: watch it here.

    7 reactions
Trending awards, every completed day and week
Gold
2791st place finishes
Silver
2872nd place finishes
Bronze
3213rd place finishes
Awarded repositories
103Owned by Microsoft now

Repositories

Ordered by gold, then silver, then bronze.

  1. generative-ai-for-beginnersBest: 1st by forks, 3,366 forks332935
  2. winget-pkgsBest: 1st by PR authors, 685 PR authors3190132
  3. ML-For-BeginnersBest: 1st by stars, 5,211 stars251413
  4. Web-Dev-For-BeginnersBest: 1st by stars, 2,783 stars181311
  5. MS-DOSBest: 1st by stars, 4,923 stars1482
  6. markitdownBest: 1st by stars, 16,730 stars12116
  7. calculatorBest: 1st by stars, 10,413 stars1044
  8. terminalBest: 1st by stars, 32,014 stars9104
  9. BitNetBest: 1st by stars, 4,562 stars720
  10. visual-chatgptBest: 1st by stars, 13,309 stars625
  11. OmniParserBest: 1st by stars, 8,088 stars623
  12. vscodeBest: 1st by stars, 6,883 stars602
  13. c9-python-getting-startedBest: 1st by stars, 820 stars550
  14. typescript-goBest: 1st by stars, 15,248 stars500
  15. IoT-For-BeginnersBest: 1st by stars, 4,733 stars440
  16. autogenBest: 1st by stars, 3,238 stars431
  17. graphragBest: 1st by stars, 6,732 stars430
  18. CNTKBest: 1st by stars, 1,664 stars421
  19. winfileBest: 1st by stars, 3,700 stars412
  20. winget-cliBest: 1st by stars, 4,809 stars410
  21. WinObjCBest: 1st by stars, 3,392 stars410
  22. WSLBest: 1st by stars, 7,755 stars410
  23. ChakraCoreBest: 1st by stars, 4,104 stars401
  24. fluentui-emojiBest: 1st by stars, 3,931 stars400
  25. Data-Science-For-BeginnersBest: 1st by stars, 517 stars344
  26. playwrightBest: 1st by stars, 5,761 stars332
  27. VibeVoiceBest: 1st by stars, 749 stars325
  28. cascadia-codeBest: 1st by stars, 553 stars240
  29. inshellisenseBest: 1st by stars, 5,882 stars221
  30. reactxpBest: 1st by stars, 1,499 stars221
  31. windows-rsBest: 1st by stars, 695 stars221
  32. playwright-mcpBest: 1st by stars, 1,396 stars220
  33. ai-eduBest: 1st by stars, 568 stars202
  34. TypeScriptBest: 1st by stars, 453 stars202
  35. everyonecancodeBest: 1st by forks, 249 forks201
  36. STLBest: 1st by stars, 1,804 stars201
  37. GW-BASICBest: 1st by stars, 1,271 stars200
  38. PowerToysBest: 1st by stars, 675 stars1412
  39. napajsBest: 1st by stars, 1,886 stars141
  40. frontend-bootcampBest: 1st by stars, 1,659 stars123
  41. garnetBest: 1st by stars, 1,518 stars120
  42. AI-For-BeginnersBest: 1st by stars, 9 stars113
  43. FASTERBest: 1st by stars, 628 stars110
  44. magentic-uiBest: 1st by stars, 653 stars110
  45. mimallocBest: 1st by stars, 640 stars110
  46. msbuildBest: 1st by stars, 861 stars110
  47. qdkBest: 1st by forks, 64 forks110
  48. WSL2-Linux-KernelBest: 1st by stars, 1,099 stars110
  49. dotnetBest: 1st by PR authors, 24 PR authors106
  50. ailabBest: 1st by stars, 788 stars103
  51. azuredatastudioBest: 1st by stars, 791 stars101
  52. codetourBest: 1st by stars, 386 stars101
  53. fluentui-system-iconsBest: 1st by stars, 726 stars101
  54. Microsoft-3D-Movie-MakerBest: 1st by stars, 1,460 stars101
  55. FluidFrameworkBest: 1st by stars, 799 stars100
  56. nodeBest: 1st by stars, 403 stars100
  57. ProcDump-LinuxBest: 1st by stars, 594 stars100
  58. ProcMon-LinuxBest: 1st by stars, 768 stars100
  59. service-fabricBest: 1st by stars, 887 stars100
  60. wslgBest: 1st by stars, 632 stars100
  61. api-guidelinesBest: 2nd by stars, 1,511 stars040
  62. azurechatBest: 2nd by stars, 1,066 stars033
  63. DeepSpeedBest: 2nd by stars, 3,576 stars033
  64. editBest: 2nd by stars, 2,553 stars031
  65. BosqueLanguageBest: 2nd by stars, 702 stars021
  66. promptbaseBest: 2nd by stars, 755 stars021
  67. SPTAGBest: 2nd by stars, 1,104 stars021
  68. ai-agents-for-beginnersBest: 2nd by forks, 129 forks015
  69. promptflowBest: 2nd by stars, 838 stars012
  70. qlibBest: 2nd by forks, 130 forks012
  71. TRELLISBest: 2nd by stars, 532 stars012
  72. TypeChatBest: 2nd by stars, 554 stars012
  73. agent-frameworkBest: 2nd by stars, 372 stars011
  74. AirSimBest: 2nd by stars, 372 stars011
  75. fastBest: 2nd by stars, 329 stars011
  76. vscode-copilot-chatBest: 2nd by stars, 1,017 stars011
  77. data-formulatorBest: 2nd by stars, 1,258 stars010
  78. ELLBest: 2nd by stars, 348 stars010
  79. malmoBest: 2nd by stars, 431 stars010
  80. monaco-editorBest: 2nd by stars, 881 stars010
  81. openvmmBest: 2nd by stars, 622 stars010
  82. Power-FxBest: 2nd by stars, 599 stars010
  83. prompt-engineBest: 2nd by stars, 719 stars010
  84. pyrightBest: 2nd by stars, 974 stars010
  85. RustTrainingBest: 2nd by stars, 377 stars010
  86. SandDanceBest: 2nd by stars, 445 stars010
  87. StudentsAtBuildBest: 2nd by PR authors, 142 PR authors010
  88. veronaBest: 2nd by stars, 598 stars010
  89. VFSForGitBest: 2nd by stars, 759 stars010
  90. JARVISBest: 3rd by stars, 2,406 stars005
  91. BASIC-M6502Best: 3rd by stars, 427 stars002
  92. ethrBest: 3rd by stars, 1,765 stars002
  93. ApplicationInspectorBest: 3rd by stars, 612 stars001
  94. BlingFireBest: 3rd by stars, 735 stars001
  95. checkedcBest: 3rd by stars, 436 stars001
  96. computervision-recipesBest: 3rd by stars, 481 stars001
  97. faraBest: 3rd by stars, 290 stars001
  98. join-dev-designBest: 3rd by PR authors, 42 PR authors001
  99. Mastering-GitHub-Copilot-for-Paired-ProgrammingBest: 3rd by stars, 791 stars001
  100. msquicBest: 3rd by stars, 424 stars001
  101. pomlBest: 3rd by stars, 382 stars001
  102. sudoBest: 3rd by stars, 1,080 stars001
  103. TouchDevelopBest: 3rd by stars, 413 stars001

A repository earns an award for finishing first, second or third in a completed trending day or week, ranked by new stars, new forks or pull request authors. Awards follow a repository through renames and transfers and count toward its current owner. Weeks run Monday to Sunday, UTC.