CodexでAstro改修をLunaとAstraに任せて比較―小さな改修に高性能モデルは必要なのか?
CodexのGPT-5.6 LunaとGPT-6 Astraへ実際のAstro改修を任せ、TOP、404、リンク切れ検出、画像最適化で時間・差分・検証範囲・利用枠を比較。4回目はAstraを思考量「軽」まで下げましたが、5時間枠を使い切り比較タスクを完走できませんでした。

Codexでモデルを切り替えられるようになると、どこから高性能モデルを使うべきかが気になる。
大きなリファクタリングなら高性能モデルを選ぶ理由は分かりやすい。一方で、実際の開発では数ファイルだけを触る小さな改修も多い。そのたびに上位モデルを使う必要があるのかは、ベンチマークだけでは判断しにくい。
そこで、ゆまラボのAstroプロジェクトに実際に必要になった改修を、CodexのGPT-5.6 LunaとGPT-6 Astraへ任せて記録している。初回と2回目はモデル以外の条件をそろえ、3回目ではAstraの思考量を意図的に下げた。
比較したのは回答文のうまさではない。
- 実装が終わるまでの時間
- 実際に実行したコマンド
- 調査や検証の手順
- 変更したファイルと差分
- ビルド失敗ややり直し
- 最終的な画面とHTML
- CodexとWorkで共有している5時間・週間利用枠の変化
を記録した。
初回はTOPページの「新着記事」を「新着・更新記事」へ変更し、2回目はカスタム404ページを作った。3回目は、記事やページから存在しない内部URLへリンクしている場合に、npm run buildで検出して失敗させる処理を追加した。
この記事は継続更新する。今後も、ゆまラボで実際に行う改修で比較を追加していく予定だ。
更新履歴#
- 2026年9月12日:検証4。本文画像の最適化を追加。Astraは思考量「軽」で実行したが5時間枠を使い切り、比較タスクを完走できず
- 2026年9月11日:検証3。内部リンク切れ検出を追加。Astraは思考量を「中」まで下げて実行
- 2026年9月10日:検証2。カスタム404ページ作成の比較を追加
- 2026年9月9日:初版。TOPページの「新着・更新記事」対応でLunaとAstraを比較
最初の検証はTOPページの小さな改修#
ゆまラボでは、公開済みの記事へ大きな追記をした場合にupdatedAtを更新している。
ただ、TOPページの記事一覧は公開日の新しい順で表示していた。継続更新する記事を増やすなら、更新した古い記事もTOPへ戻したい。
今回Codexへ渡した要件は次の3点。
- TOPの「新着記事」を「新着・更新記事」へ変更する
- TOPだけ、
updatedAt ?? pubDateを基準に新しい順で表示する - 更新記事では「更新日」と「公開日」を分けて表示する
/blog/の記事一覧、カテゴリ、サブカテゴリ、タグ、シリーズなど、TOP以外の並び順は変更しない条件も付けた。
依頼時はupdatedDate ?? pubDateという表現を使っていたが、実際のContent Schemaを確認すると、このプロジェクトでは更新日にupdatedAtを使っている。LunaもAstraも既存スキーマを確認し、実装ではupdatedAt ?? pubDateを使っている。
概念としては次の処理になる。
const latestDate = post.data.updatedAt ?? post.data.pubDate;
今回の作業は、要件が明確で、対象もTOP周辺に限定されている。最初の比較対象として扱いやすい規模だ。
同じBASE_COMMITから別ブランチを作った#
モデル比較では、一方がもう一方の実装を引き継ぐ状態を避けた。
開始時のGit状態はclean。BASE_COMMITは次のコミットで固定した。
7cbc718d20173c20ff2a62314f478aa59b1d0403
Luna用とAstra用に別ブランチを作った。
experiment/top-latest-updated-luna
experiment/top-latest-updated-astra
Luna側を完了してcommitした後、AstraはLunaブランチを引き継がず、同じBASE_COMMITから開始している。
モデルの切り替えだけはCodex側に任せず、手動で行った。

Luna側の実装が終わった後、GPT-6 Astraへ切り替えた。

モデル選択画面では、どちらも「極高」の表示になっている状態で実行した。
ただし、この比較は完全なブラインドテストではない。
Astra開始時にLunaのdiffや保存済み比較ファイルを新しく読ませない条件にはしたが、同じCodexの会話にはLuna作業時の履歴が残っている。またnode_modulesやビルドキャッシュも同じローカル環境を使っている。
同じコードと同じ依頼から独立実装している。ただし、研究用途の厳密なベンチマークではなく、普段のCodex利用に近い実測として扱う。
利用枠は開始前後の画面を保存した#
Codexから5時間・週間利用枠の数値を直接ログへ取得することはできなかった。そのため、モデルを動かす前後に「CodexとWorkのアナリティクス」を開いて画面を保存した。
Luna開始前の表示は、5時間枠が99%残り、週間利用上限が86%残り。

Luna終了後は、5時間枠が98%残り、週間は86%残りのまま。ここをそのままAstra開始前の基準にした。

この時点までの表示差は単純だ。
| モデル | 5時間枠 開始 | 5時間枠 終了 | 週間枠 開始 | 週間枠 終了 |
|---|---|---|---|---|
| GPT-5.6 Luna | 99%残り | 98%残り | 86%残り | 86%残り |
| GPT-6 Astra | 98%残り | 後述 | 86%残り | 後述 |
ここで使っている「1%」「98%」は、トークン数や料金を表しているわけではない。管理画面に表示される残量の整数値だ。
OpenAIの公式案内でも、WorkとCodexは利用枠を共有し、5時間枠と週間枠の両方が使われる場合があるとしている。実際にどれだけ使えるかは、モデル、タスク、入力と出力の大きさ、推論設定などで変わる。
この点は、後でAstraの結果を見るとかなり重要になる。
Lunaは5分17秒で実装を完了#
Lunaの計測開始は2026年9月9日18時40分33秒。
実装、ビルド、指定ケースの確認は18時45分51秒に完了した。
経過時間: 00:05:17.8874742
約5分18秒。
ログ上の結果は次の通り。
| 項目 | Luna |
|---|---|
| 実装・確認時間 | 5分17.887秒 |
| ターミナル呼び出し | 20回 |
| 観測可能な作業ステップ | 13 |
| ソース変更ファイル | 4 |
| 追加行 | 20 |
| 削除行 | 10 |
| ビルド失敗 | 0 |
| サイト実装のやり直し | 0 |
| テスト記述の修正 | 1 |
| ユーザー追加指示 | 0 |
Lunaは最初にTOP、記事カード、日付コンポーネント、Content Schema、既存のソート処理を調べた。
実装は4ファイルに分かれた。
src/components/ArticleCard.astro
src/components/FormattedDate.astro
src/pages/index.astro
src/utils/posts.ts
特徴は、今回の処理を既存コンポーネント側へ少し一般化したことにある。
src/utils/posts.tsには、更新日を優先する比較関数を追加した。
export const sortPostsByLatestDate = (a: BlogPost, b: BlogPost) =>
(b.data.updatedAt ?? b.data.pubDate).valueOf() -
(a.data.updatedAt ?? a.data.pubDate).valueOf() ||
b.id.localeCompare(a.id, 'ja', { numeric: true });
TOPではこの関数を使う。
const posts = [...allPosts]
.sort(sortPostsByLatestDate)
.slice(0, 6);
ArticleCard.astroにはshowUpdatedAtを追加し、TOPから指定した場合だけ更新日と公開日を2段で表示するようにした。
さらにFormattedDate.astroへcompact表示を追加している。
既存部品を拡張して再利用する方向の実装になっている。
途中で1回だけ、指定ケースを確認するfixtureのDate変換順を誤り、テストが終了コード1になった。原因はサイト実装ではなくテスト記述側。fixtureを修正した後はPASSしている。
最終的なnpm run buildは終了コード0。
160 page(s) built
Pagefind: Indexed 47 pages
既存のnode scripts/verify.mjsもPASSしている。
Astraは3分29秒。変更は2ファイルに収まった#
Astraの実装計測は19時01分04秒に開始した。
実装、正式ビルド、必要な確認を完了した時刻は19時04分34秒。
経過時間: 209.981秒
3分29.981秒。
Lunaより107.906秒短い。Lunaの実装時間を基準にすると、約33.9%短い。
Astra側の記録はこちら。
| 項目 | Astra |
|---|---|
| 実装・確認時間 | 3分29.981秒 |
| 計測区間のターミナル呼び出し | 14回 |
| 観測可能な作業ステップ | 20 |
| ソース変更ファイル | 2 |
| 追加行 | 16 |
| 削除行 | 4 |
| ビルド失敗 | 0 |
| サイト実装のやり直し | 0 |
| 追加検証スクリプトの修正 | 2 |
| ユーザー追加指示 | 0 |
Astraが変更したサイト本体のファイルは2つだけ。
src/components/ArticleCard.astro
src/pages/index.astro
TOPだけで使うソートはindex.astroの中に置いている。
const posts = [...allPosts].sort((a, b) =>
(b.data.updatedAt ?? b.data.pubDate).valueOf() -
(a.data.updatedAt ?? a.data.pubDate).valueOf()
).slice(0, 6);
日付表示は、ArticleCardにnamed slotを1つ追加した。
<slot name="dates"><FormattedDate date={post.data.pubDate} /></slot>
TOP側からだけdatesを渡す。
<ArticleCard post={post}>
<span slot="dates" class="card-dates">
{post.data.updatedAt && (
<span>
更新 <time datetime={post.data.updatedAt.toISOString()}>
{formatDate(post.data.updatedAt)}
</time>
</span>
)}
<span>
公開 <time datetime={post.data.pubDate.toISOString()}>
{formatDate(post.data.pubDate)}
</time>
</span>
</span>
</ArticleCard>
Lunaが共通部品を拡張したのに対し、Astraは今回必要なTOPだけへ処理を寄せた。
変更範囲だけを見るとAstraの方が小さい。
一方で、Astraは実装後の検証にかなり手をかけている。
Astroテンプレートを単独コンパイルして指定ケースを確認するverify-astra.mjsを作り、最初の実行でcreateMetadata関連のエラーが出た。
その後、実際のAstroコンパイル処理やbindingの型定義まで確認し、runtime指定を変更。2回目も同じエラーになったため、さらにresolvePathを追加して3回目でPASSしている。
ここはサイトコードを直し直したわけではない。Astra自身が追加した検証コード側で2回手戻りが発生した。
それでも正式なnpm run buildは最初から成功している。
160 page(s) built
Pagefind: Indexed 47 pages
ビルド失敗は0回。
画面はLunaとAstraで同じになった#
両ブランチをそれぞれビルドし、生成結果も比較した。
Luna側のTOPはこちら。

Astra側はこちら。

見た目だけでは違いが分からない。
比較スクリプトでも、現在TOPに表示される6カードは同一になった。
さらにブラウザで1440×1000と390×844の2サイズを確認し、両方とも横方向のoverflowはなし。日付表示のテキストとジオメトリも同一になった。
TOP以外については、Astroのscope属性、stylesheet、空白だけを正規化して159ページを比較したが、差分は0ページ。
つまり今回要求した「TOPだけ変更し、その他の一覧へ影響させない」は両方とも満たしている。
指定ケースも両方PASSした。
公開日のみ
→ 公開 2026.09.09
更新日あり
→ 更新 2026.09.10
→ 公開 2026.09.01
2026.09.12更新の記事と2026.09.11公開の記事
→ 更新記事を先に表示
機能的な完成結果には差がなかった。
同じ日付の記事だけ、並び方が違う#
完全に同じ実装ではないため、1つだけ挙動差が見つかった。
updatedAt ?? pubDateで求めた基準日が同じ記事同士の順序だ。
Lunaは比較関数の最後で記事IDを使っている。
b.id.localeCompare(a.id, 'ja', { numeric: true })
一方Astraは基準日の差だけを返しているため、同じ日付なら元の配列順を維持する。元の配列は公開日順なので、結果としてその順序が残る。
比較用データでは次の差になった。
| 条件 | Luna | Astra |
|---|---|---|
| 基準日が同じ2記事 | 記事IDによる順序 | 元の公開日順を維持 |
今回の依頼には「同じ基準日のとき何で並べるか」を指定していなかったため、どちらも要件違反ではない。
ただ、今後本番へ採用するなら決めておいた方がよい仕様だと思う。
更新日まで同じ記事が複数ある場合に、公開日を第2キーにするのか、記事IDを使うのか。今回の比較で、モデルによってこうした細部の判断が変わることも確認できた。
2つの実装は方向が違う#
結果の画面は同じでも、コードの作り方は分かれた。
| Luna | Astra | |
|---|---|---|
| 変更ファイル | 4 | 2 |
| 差分 | +20 / -10 | +16 / -4 |
| ソート処理 | posts.tsへ共通関数追加 | TOPに直接記述 |
| 日付表示 | ArticleCardへprop追加 | named slot追加 |
| 日付フォーマット | FormattedDateを拡張 | TOP内の関数 |
| 方向 | 再利用できる形へ拡張 | TOP限定の変更に寄せる |
Lunaの実装は、今後ほかの場所でも「最終更新日順」を使ったり、FormattedDateのコンパクト表示を再利用したりするなら扱いやすい。
Astraの実装は、依頼どおり「TOPだけ」を強く意識している。既存の共通コンポーネントへ手を入れる範囲が小さく、今回だけなら影響範囲を追いやすい。
どちらが正しいという差ではない。
小さい改修でも、AIがどこまで共通化するかには違いが出る。
時間だけならAstraが速い#
ここまでの実装結果を並べる。
| 項目 | GPT-5.6 Luna | GPT-6 Astra |
|---|---|---|
| 実装・確認時間 | 5分17.887秒 | 3分29.981秒 |
| Lunaとの差 | - | 1分47.906秒短い |
| ターミナル呼び出し | 20 | 14(計測区間) |
| 観測可能な作業ステップ | 13 | 20 |
| ソース変更ファイル | 4 | 2 |
| ソース差分 | +20 / -10 | +16 / -4 |
| ビルド失敗 | 0 | 0 |
| サイト実装のやり直し | 0 | 0 |
| 検証コード側の失敗 | 1 | 2 |
| 最終画面 | 要件達成 | 要件達成 |
| TOP以外への影響 | なし | なし |
Astraは実装時間を約34%短縮した。
ただし「作業ステップ数」はそのままモデル性能として比較しない方がよい。
Lunaのログは一部のコマンドで実行時刻を直接取得できず、複数確認を1つの手順として記録している。Astra側はJSONでシェル呼び出しを細かく保存し、外部ドキュメント参照や検証スクリプト修正も1ステップずつ数えている。
同じ計数方法ではないため、13対20だけを見て「Astraの方が手順が多い」と断定はできない。
比較しやすいのは、実装開始と終了を記録した経過時間、Git差分、ビルド結果、最終出力だ。
Astra終了時の利用枠は、その場で取り損ねた#
今回、特に差が大きく見えたのが利用枠の変化だ。
ただし、ここは測定上の注意がある。
Astraは19時04分34秒に実装、ビルド、指定確認を完了した。その時点でCodexは次のチェックポイントを表示している。
USAGE CHECKPOINT - ASTRA END
5時間制限と週次制限の使用量を確認・スクリーンショット保存してください。
本来ならここで画面を保存すれば、Astraの実装だけに近い差を取れた。
その直後にCodexが比較作業へ進んだ。
ログには、19時05分31秒以降にLuna側のログとdiffの読み込み、Lunaブランチの再ビルド、両出力の比較、ブラウザ確認が残っている。
19:05:31 Lunaの結果とdiffを読み込み
19:05:56 Lunaブランチへ切り替え
19:05:58 Lunaを再ビルド
19:07:44 両出力を比較
19:08:34 ブラウザでLuna/Astraを確認
その後、Codex側で利用上限に達した。
最終的に保存できた画面はこちら。

開始前と最終画面だけを並べると、次の変化になる。
| 5時間枠 | 週間枠 | |
|---|---|---|
| Luna開始前 | 99%残り | 86%残り |
| Luna終了 / Astra開始前 | 98%残り | 86%残り |
| Astra作業と後続比較の終了後 | 0%残り | 71%残り |
Lunaでは表示上、5時間枠が1ポイント減り、週間枠は整数表示上変化しなかった。
Astra側は、Astra開始前の98%から最終的に0%になり、週間枠も86%から71%になった。
ただし、「Astraの3分29秒の実装だけで98ポイント消費した」とは書けない。
0%の画面を保存した時点には、実装後の比較、Luna再ビルド、HTML比較、ブラウザ確認などが含まれている。Astra実装終了直後の中間値を記録できていないためだ。
また、このパーセントは内部トークン消費量そのものではない。
それでも、小規模な同一作業でLuna終了時には98%残っていた5時間枠が、Astraへ切り替えた後の一連の作業で上限まで到達したことは、実際の運用では無視しにくい結果になった。
Astraは実装以外の検証にも動いている#
Astraのログを見ると、単純に2ファイルを書き換えて終わったわけではない。
実装の前後で、次の確認を行っている。
- AGENTS.md、package.json、TOP、ArticleCard、FormattedDate、Content Schema、posts.tsをまとめて確認
- Astro公式ガイドを参照
- 既存verifyスクリプトとAstro設定を確認
npm run build- Astro Containerやcompiler-rsの型定義を確認
- 独自の
verify-astra.mjsを作成 createMetadataエラーを2回調査- Astro本体の
compile.jsとbinding型定義を確認 - 指定ケースを再実行
git diff --check
実装完了後にはさらに、Lunaブランチを再ビルドし、HTML差分とブラウザ表示まで比較した。
ここまで含めて見ると、Astra側の作業は「コードを書く時間」だけではない。
ソース変更はLunaより小さい一方、検証のために低レベルなAstroコンパイラまで追っている。
この追加検証が利用枠にどの程度影響したかは分からない。OpenAIも、Work/Codexの消費量はモデル、タスク、入出力サイズ、推論設定などによって変わるとしているため、1回の結果から原因を分解することはできない。
ただ、実際にCodexへ「比較用のログを細かく残し、ビルドと挙動まで確認してほしい」と頼むと、高性能モデルが実装以上の確認へ広く動くケースがあることは記録できた。
小さな改修ではLunaで要件を満たせた#
今回のタスクだけで見ると、Lunaで不足はなかった。
Lunaは5分17秒で要件を満たし、ビルドも成功。Astraはそこから約1分48秒短縮し、ソース変更を2ファイルに収めた。
最終画面は同じ。TOP以外への影響もない。
Astraには、短時間で局所的な変更へ寄せた利点がある。一方で、この程度の改修で最終的な機能差は出なかった。
利用枠については測定タイミングの問題があるため、AstraとLunaの消費倍率を出すことはできない。それでも、今回の一連のAstra作業で5時間枠の上限まで到達し、その後Codexを続けられなくなったことは無視できない。
小さく、要件が明確で、変更対象が数ファイルに限られる作業なら、まずLunaで進める運用は十分現実的だと思う。
逆に、複数の機能を横断する改修、影響範囲の広い変更、難しい不具合調査では、Astraが短い時間や少ない手戻りで終わるなら利用枠を多く使う意味が出てくるかもしれない。
そこは今回1件だけでは判断できない。
検証2:カスタム404ページを同じ条件で作る#
2回目の検証は、ゆまラボ専用の404ページ追加にした。
対象は、存在しないURLへアクセスしたときに、通常のヘッダーとフッターを残しながら「ページが見つかりません」と表示し、トップページと記事一覧へ戻れるようにする改修。
実装内容は第25回 ゆまラボ専用の404ページを作る―存在しないURLから記事へ戻れる導線を追加にまとめている。
初回比較で残った測定上の問題も修正した。
最初のTOP改修では、Astraが実装を終えた後もCodexが比較処理を続けたため、Astra終了直後の利用枠を記録できなかった。そこで検証2では、モデルごとに実装、ビルド、ローカル確認が完了した時点でCodexを停止し、その直後に利用枠画面を保存した。
また、LunaとAstraは別のCodexチャットで実行した。開始地点だけを共通のBASE_COMMITへ固定し、AstraにはLuna側のdiffや実装コードを読ませていない。
同じBASE_COMMITから404ページを作る#
開始地点は次のコミット。
9e1d2e67be253e660303ec9a143ca62497f844f8
ブランチも分けた。
experiment/404-page-luna
experiment/404-page-astra
BASE_COMMITの時点では、src/pages/404.astroとsrc/pages/404.mdはどちらも存在していない。
一方、Cloudflare Workers側のwrangler.jsoncには、すでに次の設定が入っていた。
{
"assets": {
"not_found_handling": "404-page"
}
}
そのため、両モデルへ要求したサイト本体の変更はsrc/pages/404.astroの追加だけになる。
共通条件は次の通り。
SiteLayoutなど既存のレイアウトを再利用する- 404と「ページが見つかりません」を表示する
- トップページと記事一覧へ移動できるようにする
- 通常ページのURLや既存機能を変更しない
- 存在しないURLをトップへリダイレクトしない
- Astro previewとWranglerでHTTP 404を確認する
- PCとスマホ幅への影響も確認する
利用枠は実装終了直後に保存した#
Luna開始前は、5時間枠が93%残り、週間枠が70%残り。


Lunaが実装、ビルド、ローカル確認を終えたところで追加作業を停止した。直後の表示は5時間89%残り、週間69%残り。

ここから新しいCodexチャットを開き、GPT-6 Astraへ切り替えた。

Astra開始前の利用枠は、Luna終了直後と同じ5時間89%残り、週間69%残り。

Astra側も実装、ビルド、ローカル確認が終わった時点で比較処理へ進ませず停止した。終了直後は5時間32%残り、週間60%残りになった。

管理画面の表示値をそのまま並べるとこうなる。
| モデル | 5時間枠 開始 | 5時間枠 終了 | 表示差 | 週間枠 開始 | 週間枠 終了 | 表示差 |
|---|---|---|---|---|---|---|
| GPT-5.6 Luna | 93%残り | 89%残り | -4pt | 70%残り | 69%残り | -1pt |
| GPT-6 Astra | 89%残り | 32%残り | -57pt | 69%残り | 60%残り | -9pt |
前回と違い、両モデルとも実装終了直後に画面を保存している。少なくとも前回のように、Astra終了後のLuna再ビルドや比較処理が混ざった値ではない。
ただし、この数字をそのまま「AstraはLunaの14.25倍トークンを使った」とは扱わない。
表示は整数単位の残量であり、トークン数ではない。WorkとCodexの利用枠はモデル、タスク、入出力、推論設定などでも変わる。今回確認できる事実は、同じ404実装で管理画面上の5時間枠がLunaでは4ポイント、Astraでは57ポイント低下したことまでになる。
OpenAIの案内でも、同じタスクでもモデルによって利用枠の消費量が異なり、Astraは利用枠を速く使う場合があるとしている。今回の実測でも、その差を無視しにくい結果になった。
Lunaは93行、Astraは30行で同じ要件を満たした#
両モデルとも変更したサイト本体のファイルは1つだけ。
src/pages/404.astro
追加パッケージもなく、package.json、astro.config.mjs、wrangler.jsoncは変更していない。
ただし、作った404.astroの構成はかなり違う。
Luna側は93行。
404の数字を大きく中央へ配置し、サイト名の表示、中央寄せ、ボタン風の戻りリンク、520px以下でリンクを縦積みにするメディアクエリまでページ内へ持たせた。
実装の主要部分は次の形。
<main class="not-found">
<p class="eyebrow">{SITE_TITLE}</p>
<p class="status">404</p>
<h1>{title}</h1>
<p class="message">
ゆまラボ内のページが見つかりませんでした。
URLをご確認いただくか、次のページからお探しください。
</p>
<nav class="actions" aria-label="404ページのナビゲーション">
<a class="primary" href="/">トップページへ戻る</a>
<a href="/blog/">記事一覧を見る</a>
</nav>
</main>
Astra側は30行。
通常の記事や固定ページに近い左寄せの余白を使い、404、見出し、説明、2本のテキストリンクだけに絞った。
<main>
<section class="not-found" aria-labelledby="not-found-title">
<p class="error-code">404</p>
<h1 id="not-found-title">{title}</h1>
<p class="description">
お探しのページは、URLが変更されたか、削除された可能性があります。<br />
トップページや記事一覧から記事をお探しください。
</p>
<nav class="return-links" aria-label="404ページからの移動先">
<a href="/">トップページへ戻る</a>
<a href="/blog/">記事一覧を見る</a>
</nav>
</section>
</main>
要件達成だけを見ると両方とも同じ。
Lunaは404ページ単体のUIをはっきり作る方向、Astraは現在のゆまラボの通常レイアウトへ寄せて変更量を小さくする方向になった。
公開後の画面はこちら。

公開画面の文言とレイアウトはAstra側の実装と一致している。本番へ反映されたのはAstra案。
Astraはブラウザ確認まで自力で広げた#
実装時間以外にも差が出た。
LunaはAstro previewとWranglerを起動し、正常URLが200、存在しないURLが404になることを確認した。ただしブラウザ自動操作環境を利用できないと判断し、PC・スマホはHTMLとCSSの静的確認で終了している。
その途中で検証系の失敗が3回あった。
- previewサーバーへの初回接続失敗
- PowerShellのHttpClient型指定エラー
- Nodeコマンドのシェルクォートエラー
サイト本体の修正は必要なく、すべて確認処理側の失敗として解消している。
Astraはプロジェクト内にPlaywright等がないことを確認したあと、同じWindows環境にインストールされているMicrosoft Edgeを見つけ、CDPを使った確認処理を追加した。
結果として、Astro previewとWranglerの2環境で36回のHTTP確認を実施。正常ページ、複数の存在しないURL、HEADリクエストまで確認している。
PCは1440×900、スマホは390×844でスクリーンショットも保存し、トップページと記事一覧のリンクを実際にクリックした。


ここは利用枠の差を見るうえで無視できない。
Astraは同じ1ファイルの実装でも、Lunaより確認範囲を広く取っている。高性能モデルの利用枠が単純に「30行のコードを書くためだけ」に使われたとは見ない方がよい。
標準化した実装時間ではAstraが約2分3秒短い#
今回、比較用ログで定義した計測区間は、実装調査開始から、実装・ビルド・ローカル確認が終わるまで。
結果はこちら。
| 項目 | GPT-5.6 Luna | GPT-6 Astra |
|---|---|---|
| 比較用の計測時間 | 5分16.822秒 | 3分13.527秒 |
| Lunaとの差 | - | 2分03.295秒短い |
| ソース変更ファイル | 1 | 1 |
| ソース差分 | +93 / -0 | +30 / -0 |
| コマンド記録 | 26エントリ | 15シェル呼び出し |
| 観測可能な作業ステップ | 10 | 16 |
| ビルド回数 | 2 | 1 |
| ビルド失敗 | 0 | 0 |
| サイト実装のやり直し | 0 | 0 |
| 検証失敗 | 3 | 0※ |
| ブラウザ実画面確認 | できず | PC・スマホ確認 |
| HTTP 404 | preview / Wranglerで確認 | preview / Wranglerで確認 |
※Astraには計測開始前に文字コードの読み直しとオーケストレーション側のReferenceErrorが1件ずつあったが、実装計測区間の検証失敗には含めていない。
AstraはLunaより123.295秒短く、Lunaの時間を基準にすると約38.9%短い。
一方、Codexの画面にはAstraのセッション全体として「5m 53s間作業しました」と表示された。比較ログで定義した開始・終了区間に加え、事前確認や終了後のログ保存・コミットなども含む表示と考えられる。
モデル間の比較表では、Luna/Astraで同じ定義を使えるログ上の3分13.527秒を採用する。
速度差より利用枠の差の方が大きく見える#
初回のTOP改修ではAstraが約34%短時間だったが、終了直後の利用枠を保存できなかった。
今回の404実装では、計測時間でもAstraが約39%短い。
ここまでなら、Astraは同じ要求を短時間で処理したと言える。
ただ、利用枠の表示差はそれ以上に大きかった。
Luna
5時間枠 93% → 89%
週間枠 70% → 69%
Astra
5時間枠 89% → 32%
週間枠 69% → 60%
最終機能はどちらも、
- カスタム404を表示する
- トップへ戻れる
- 記事一覧へ移動できる
- 正常URLは200
- 存在しないURLは404
を満たしている。
今回の作業だけなら、Astraでなければ実装できなかった機能はない。
その一方、Astraはブラウザを見つけて実際のPC・スマホ表示まで検証し、HTTP確認も広く行った。この確認範囲を含めた品質確認まで任せたい場合は、利用枠を多く使っている理由の一部として見ることもできる。
それでも、5時間枠が57ポイント低下した事実は運用上かなり大きい。
短い改修を何本も続ける日なら、今回のような404ページ追加ではLunaを使い、難しい不具合調査や広い影響範囲の変更にAstraを残す運用の方が扱いやすい。
検証2までの段階では、その判断が初回より強くなった。
検証3:内部リンク切れをビルド時に検出する#
3回目は、これまでよりビルド処理へ踏み込む改修にした。
対象は、記事やページに存在しない内部URLへのリンクが含まれていた場合に、npm run buildの中で検出してビルドを失敗させる処理。
実装内容は第26回 記事内リンク切れをビルド時に検出する―記事が増えても404を残さない仕組みを作るにまとめている。
修正前は、記事へ次のような存在しない内部リンクを追加してもビルドが成功していた。
[リンク切れ確認用](/blog/__broken-link-test__/)
AstroはHTMLを生成し、Pagefindとsitemapの処理も完了する。
最終的に生成されたdistのHTMLを検査し、内部リンクのリンク先が実際の出力に存在するか確認する処理を追加した。
要求した主な条件は次の通り。
npm run buildだけで内部リンク検査まで実行する- 記事Markdownだけではなく、生成されたHTMLを基準にする
/始まり、相対URL、https://bringain.com/の同一サイト絶対URLを扱う- queryとhashはページ本体の存在確認から外す
- RSS、XML、画像、PDFなどの静的ファイルも存在すれば正常扱いする
- 外部サイトへHTTPリクエストを送らない
- リンク切れがあればリンク元とリンク先を表示する
- 複数件あれば一覧化してから終了コード1にする
- 意図的なリンク切れで実際にbuildが失敗することを確認する
- テスト用リンクを削除した後、再度buildが成功することを確認する
Astraの思考量を「中」に下げた#
最初の2回はLunaとAstraの思考量をどちらも「極高」にしていた。
3回目は条件を変えた。
GPT-5.6 Luna
思考量:極高
GPT-6 Astra
思考量:中
Astraは「極高」から2段下げている。
そのため、3回目はLunaとAstraを同じ推論設定で比較する実験ではない。
前回までAstraは短時間で実装を終える一方、5時間枠の表示が大きく低下していた。今回は思考量を下げ、実装要件を満たせるか、利用枠の表示差が小さくなるかを見る。
Luna終了後の変更はgit stash -uで退避した。
git stash push -u -m "broken-link-check-luna"
作業ツリーがcleanになったことを確認してから、同じHEADを起点にAstra用ブランチを作成した。
BASE_COMMIT
10e2a55213b094ce7f2a6a7b8fd51751f88442cc
experiment/broken-link-check-luna
experiment/broken-link-check-astra
AstraにはLuna側の実装コードやdiffを引き継がせていない。
Luna極高は8分6秒、Astra中は4分20秒#
計測結果は次の通り。
| 項目 | GPT-5.6 Luna | GPT-6 Astra |
|---|---|---|
| 思考量 | 極高 | 中 |
| 実装・確認時間 | 8分6.182秒 | 4分20.409秒 |
| Lunaとの差 | - | 3分45.773秒短い |
| 変更対象 | 2ファイル | 4ファイル |
| 追加パッケージ | なし | parse5を直接dev依存化 |
| 専用テストファイル | なし | あり |
| 意図的リンク切れ | 検出 | 検出 |
| リンク切れ時のbuild | 失敗 | 失敗 |
| テスト削除後のbuild | 成功 | 成功 |
git diff --check | 成功 | 成功 |
既存verify.mjs | 既存問題で失敗 | 既存問題で失敗 |
Astra中は、Luna極高より3分45.773秒短かった。
Lunaの時間を基準にすると約46%短い。
ただし、思考量が違うため、この時間差だけでモデル性能を直接比較するものではない。
確認したいのは、Astraを「中」まで下げても必要な実装と検証が完了するかどうか。
今回については、Astra中でも要求した機能は成立した。
Lunaは依存追加なし、Astraはparse5と専用テストを追加した#
両モデルは同じ目的を達成したが、実装方法は分かれた。
Luna側の変更は2件。
package.json
scripts/check-internal-links.mjs
追加パッケージはない。
dist配下のHTMLを検査するスクリプトを127行で追加し、package.jsonのbuild末尾から実行する形にした。
最初の通常buildでは、既存404ページのcanonical URL /404/をリンク切れとして1件誤検出した。
canonicalは利用者がたどるナビゲーションリンクではないため検査対象から除外し、再ビルド後は正常になった。
最終的な通常状態はこうなった。
175 generated HTML page(s)
8448 internal link(s)
0 broken links
Astra側は4件。
package.json
package-lock.json
scripts/check-links.mjs
scripts/check-links.test.mjs
HTML解析にはparse5を使った。
parse5は既存の依存ツリーに間接依存として存在していたが、スクリプトから直接使うためdevDependenciesへ明示している。
AstraはさらにURL形式や除外条件を確認する専用テストを5件作成した。
初回テストでは期待リンク数を19件と書いていたが、正しい値は18件だったため、テスト記述を修正して全件PASSしている。
サイト本体のリンク検査ロジックを直し直したわけではない。
Lunaは依存追加を避けて1本の検査スクリプトへ収め、AstraはHTMLパーサーと専用テストを明示的に追加した。
今回も、最終機能が同じでも実装の方向は一致しなかった。
どちらも意図的なリンク切れでbuildを止めた#
Luna側ではテスト用URL、
/blog/__broken-link-test__/
を追加した状態でnpm run buildを実行し、終了コード1になることを確認した。
報告されたリンク元はこのURL。
/blog/404-page-guide/
Astra側でも同じURLを使った。
実際のログは次の形。
[links] Checked 175 HTML pages, 5913 internal links; broken links: 1.
[links] "/blog/broken-links-seo/" -> "/blog/__broken-link-test__/" (/blog/__broken-link-test__/)
こちらもbuildは終了コード1。
テスト用リンクを削除したあとに再ビルドすると、
[links] Checked 175 HTML pages, 5908 internal links; broken links: 0.
となり、正常終了した。
Astro 175ページ、Pagefind 55ページ、画像最適化、sitemapの既存処理も完了している。
Astra側では通常ビルドと復元後のHTML・CSS計180ファイルのハッシュも比較し、すべて一致した。
つまり、リンク検査を追加したことによって記事HTMLやCSSが書き換わったわけではない。
内部リンク件数はLunaとAstraで一致しなかった#
ここは結果をそのまま残す。
Lunaの最終報告では、
8448 internal link(s)
Astra側では、内部リンク数が次の値になった。
5908 internal links
同じ175 HTMLページを対象としているが、数えた内部リンク数は一致していない。
この差は少し引っかかった。
両方とも意図的に追加した存在しないURLは検出し、正常状態ではbroken links 0件になっている。
ただし、内部リンク件数が違う以上、2つのスクリプトが完全に同じ集合を数えているとは扱わない。
link要素、canonical、重複URL、静的ファイルなどの数え方に実装差がある可能性はあるが、今回の記録だけで2,540件の差を1つの原因へ断定はしない。
内部リンク件数そのものはLunaとAstraの性能比較値には使わない。
本番へ採用する実装を決めるなら、リンク切れを検出できるかに加え、どの種類のhrefを検査対象へ含めるかも確認する必要がある。
思考量を下げてもAstraの利用枠表示は大きく下がった#
今回も実装終了直後に利用枠を保存した。
Luna開始前は、5時間枠100%残り、週間枠60%残り。
Luna極高の終了直後は、5時間枠97%残り、週間枠60%残り。
表示差は5時間枠が3ポイント、週間枠は整数表示上0ポイント。
この状態からAstra中を開始した。
Astra終了直後は、5時間枠37%残り、週間枠50%残り。

管理画面の表示をそのまま表にするとこうなる。
| モデル | 思考量 | 5時間枠 開始 | 5時間枠 終了 | 表示差 | 週間枠 開始 | 週間枠 終了 | 表示差 |
|---|---|---|---|---|---|---|---|
| GPT-5.6 Luna | 極高 | 100% | 97% | -3pt | 60% | 60% | 0pt |
| GPT-6 Astra | 中 | 97% | 37% | -60pt | 60% | 50% | -10pt |
Astraは思考量を「中」まで下げても、管理画面上の5時間枠は60ポイント低下した。
前回の404検証では、Astra極高で89%から32%へ57ポイント低下している。
今回の表示差だけを見ると、「思考量を2段下げれば利用枠の減少も大幅に小さくなる」という結果にはならなかった。
ただし、ここでもポイント差をトークン数や料金へ変換しない。
管理画面は整数の残量表示であり、WorkとCodexで利用枠を共有している。今回確認できるのは、実装開始前後に画面上の残量がこのように変化したことまで。
Astra中は4分20秒で要求を満たしたため、思考量を下げても実装能力が足りなかったという結果ではない。
一方、今回の目的の一つだった「Astraの思考量を下げれば利用枠を大きく節約できるか」については、この1回では確認できなかった。
3回目でも最終機能は両方成立した#
3回目まで、Astraの方が計測時間は短い。
TOP改修
Luna 5分17.887秒
Astra 3分29.981秒
404ページ
Luna 5分16.822秒
Astra 3分13.527秒
内部リンク切れ検出
Luna極高 8分6.182秒
Astra中 4分20.409秒
3回目はAstraの思考量を下げても、最終機能は両方成立した。
ただ、利用枠の表示差も3回続けてAstra側が大きい。
実装方法も、Lunaは追加依存なし、Astraはparse5と専用テストを追加する形に分かれた。
ここまでの結果では、「Astraでなければ実装できなかった」というタスクはまだない。
Astraは毎回短い時間で完了している。一方、複数の小さな改修を続ける日には、利用枠を残す目的でLunaを先に使う判断はまだ有効に見える。
難易度がさらに上がったとき、Luna側で手戻りや未達が増えるかは次の検証で確認する。
検証4:記事本文の画像をAstroで最適化する#
4回目は、これまでより対象数の多い作業にした。
記事本文に掲載しているローカル画像を調査し、Astroの画像処理を使ってWebP、srcset、sizes、width、height、遅延読み込みを追加する。
実装内容は第27回 画像表示を見直す―Astroの画像最適化と遅延読み込みでページを軽くするにまとめている。
修正前の本文画像はpublic/images/配下をそのまま参照していた。
代表画像のHTMLでは、
<img src="/images/blog/..." alt="...">
となっており、確認した要素にはsrcset、sizes、loading、width、heightが付いていなかった。
調査対象は、PNG実ファイル278件、本文内参照281件、元画像総容量44,399,561 bytes。
今回の要求には、形式変換だけでなく、PC・スマホ確認、実際に配信される画像容量、lazy loading、画像404、既存build、内部リンクチェック、既存verifyまで含めた。
Lunaは極高で27分03秒、要求した確認まで完走した#
Lunaは思考量「極高」で実行した。
開始前は5時間枠100%残り、週間枠50%残り。終了直後は5時間枠88%残り、週間枠48%残りまで減った。
表示差は5時間枠が12ポイント、週間枠が2ポイント。
作業時間は、ログ上では以下。
開始 2026-09-12 00:56:16.892 +09:00
最終確認 2026-09-12 01:23:20.556 +09:00
実作業時間 27分03.664秒
Luna側では本文画像をsrc/assetsへ移し、共通のrehypeプラグインからAstro標準の画像処理へ渡した。
代表ページでは、
srcset 320 / 480 / 640 / 720w
sizes (min-width: 720px) 720px, 100vw
形式 WebP
loading lazy
を確認している。
容量集計は、
元画像 44,399,561 bytes
生成された本文画像候補 11,315,090 bytes
削減 33,084,471 bytes
削減率 74.52%
代表ページ/blog/25-custom-404-page/では、122,901 bytesから26,698 bytesまで減り、削減率は78.28%。
npm run buildも成功。
178 page(s) built
Pagefind: Indexed 57 pages
内部リンク 6,064件
broken links 0件
PC 1440×900、スマホ390×844も確認し、スマホでは本文幅343px、画像幅343px、横スクロールなし。
既存verify.mjsは重複slugによる58対57件の不一致で失敗したが、今回の変更前から存在する問題として修正対象から外した。
Astraは思考量を最も低い側の「軽」にした#
3回目ではAstraを「中」まで下げてもリンク切れ検出を完了できた。
4回目はさらに下げ、Codex画面の表記で**「軽」**を選択した。
開始時の利用枠はLuna終了直後と同じ。
5時間枠 88%残り
週間枠 48%残り
Astra側もLuna側の変更を引き継がない状態から開始した。
Astra軽は別の方法でビルド成功まで進んだ#
Astra軽は、途中まで何もできなかったわけではない。
調査画面では、
PNG 278ファイル
本文内281参照
合計44,399,561 bytes
を確認している。
実装方針はLunaと違った。
Lunaは本文画像の実ファイルをsrc/assetsへ移したが、AstraはMarkdownと元画像をそのまま残し、共通Markdownプラグインで画像をAstroへ渡す方法を選んだ。
画面上では、変更が設定ファイルと本文画像用プラグインの2ファイルに収まったと報告されている。
ビルドも成功した。
さらにキャッシュ無効のChromeで、
代表記事の本文画像2枚
PC 30,446 bytes
スマホ 10,474 bytes
を実測し、画面下の画像がスクロールまで読み込み保留になることも確認した。
ここまでを見ると、思考量「軽」でも実装とブラウザ確認自体は進められている。
48分後に5時間枠が0%になった#
その後、Codex画面には、
48分間作業しました
と表示された。
直後に、
利用制限に達しました。
さらに利用するには、ワークスペースのオーナーにお問い合わせください。
と表示され、処理が止まった。
停止時は、5時間枠0%残り、週間枠35%残り。

Astra開始時からの表示差は、
5時間枠 88% → 0% -88pt
週間枠 48% → 35% -13pt
になる。
Astraがコードを書けなかったために失敗したわけではない。
ビルド成功、代表記事の容量測定、遅延読み込みの確認までは進んだ。
ただし、こちらが指定した全検証と最終報告を出し切る前に5時間枠を使い切った。
そのため、比較タスクとしては完走できなかったと扱う。
「軽」にしても、この規模では利用枠が足りなかった#
3回目ではAstraを「中」にし、リンク切れ検出を4分20秒で完了した。
4回目ではさらに「軽」へ下げた。
それでも48分の作業後に5時間枠が0%になった。
タスク内容が違うため、「中より軽の方が利用枠を多く使う」とは判断しない。
今回の画像最適化は、278ファイル、281参照、44MBを超える元画像を扱い、生成画像、レスポンシブ候補、PC・スマホ、Network、lazy loading、buildまで確認する要求。
今回確認できたのは、Astraの思考量を「軽」まで下げても、この規模の一連の作業を現在の残り利用枠で最後まで完走できなかったということ。
本番にはLuna版を採用する#
本番へ反映するのはLuna側の実装にした。
Luna側では、要求した容量集計、WebP生成、srcset、sizes、loading="lazy"、PC・スマホ、画像HTTP 200、正式buildまで一通り確認できている。
Astra版は実装方法としては興味深い。
Markdownと元画像を移動せず、2ファイルに変更を収めていた。
ただ、利用制限に到達したため、今回要求した最終報告を最後まで取得できなかった。
今回の結果は、「Astra軽では画像最適化できない」ではない。
実装は進んだが、今回の比較条件ではクレジットが足りず最後まで完走できなかった。
ここを分けて記録しておく。
4回分を並べると利用枠の扱いが見えてきた#
| 検証 | Luna | Astra | Astra思考量 | Astra側の結果 |
|---|---|---|---|---|
| TOPの新着・更新記事 | 5分17.887秒 | 3分29.981秒 | 極高 | 完了 |
| 404ページ | 5分16.822秒 | 3分13.527秒 | 極高 | 完了 |
| 内部リンク切れ検出 | 8分6.182秒 | 4分20.409秒 | 中 | 完了 |
| 本文画像最適化 | 27分03.664秒 | 画面表示48分 | 軽 | 利用制限到達、比較タスク未完走 |
Astraは最初の3回では毎回Lunaより短時間で要求を満たした。
4回目は思考量を「軽」まで下げたが、作業規模が大きくなったところで5時間枠を使い切った。
この4回の実測だけでモデル全体の優劣は決めない。
少なくとも今回の画像最適化では、Luna極高は27分で完走し、Astra軽は48分作業した時点で利用制限に到達した。
総評#
4回の比較では、TOP改修、404ページ、内部リンク切れ検出の3件は、LunaとAstraのどちらも最終的な要件を満たした。計測時間だけを見ると、この3件はすべてAstraの方が短かった。
一方で、利用枠の減り方はAstra側が大きかった。404ページでは5時間枠が57ポイント、内部リンク切れ検出では思考量を「中」まで下げても60ポイント低下している。表示値はトークン数そのものではないため単純な倍率比較はできないが、同じ日に複数の改修を続ける運用では無視しにくい差。
4回目の本文画像最適化では、Luna極高が27分03.664秒で要求した確認まで完走した。Astraは思考量を「軽」まで下げ、実装とビルド、ブラウザでの容量確認や遅延読み込み確認までは進んだが、48分作業した時点で5時間枠が0%になり、比較タスクを最後まで終えられなかった。
実装方法にも差が出た。Lunaは既存部品の共通化や依存追加を避ける方向を選ぶ場面があり、Astraは変更ファイルを絞ったり、専用テストや追加検証まで広げたりする場面があった。最終結果が同じでも、そこへ到達する手順はかなり違う。
今回の4件だけでモデル全体の優劣は決められない。ただ、ゆまラボで実際に使った範囲では、短時間で局所的な変更を終える速さはAstraに分があり、利用枠を残しながら複数の作業を続ける扱いやすさはLunaの方が高かった。
最終的には、モデル名だけで選ぶより、作業時間、利用枠、変更範囲、検証の広さ、最後まで完走できるかをまとめて見る必要がある、という結果になった。


