---
title: "サイトの計測を別の AI に疑わせる ― 人の来訪が急に減った理由の言い過ぎを Codex が見つけた"
slug: codex-adversarial-check-site-measurement-drop
date: 2026-11-12
day: 494
meta_description: "pixelstomotors.com で11月11日に人の表示が1日20〜30件から3件に減った理由は、まだ決められない。Claude の「故障ではない」という結論は、Codex の敵対的検証で根拠が足りないと分かった。"
tags: [アクセス解析, Codex, 敵対的検証, Search Console, LinkedIn, 計測, AIクローラー]
series: "ひとり研究所の裏側"
---

**pixelstomotors.com で2026年11月11日に人のページ表示が1日20〜30件から3件に減った理由は、11月12日の時点ではまだ決められない。** Claude は最初「計測の故障ではなく、本当に人が来なくなった」と言い切ったが、OpenAI の Codex（コードを読んで検証する AI）に穴を探させると、その根拠は機械として数えられる記録が届くことを確かめただけで、人のブラウザで記録が届くかは確かめていなかった。

この検証で、次のことが変わりました。

- 分析の言い過ぎを、公開する前に止められた。Claude が出した4つの結論のうち、2つは撤回、1つは言い方を弱め、1つは範囲を限れば言ってよいと分かった
- 計測のコードの不具合が2つ見つかった。夜中の0時をまたいで送り直された表示を2日に1件ずつ数えてしまう所と、自分の閲覧を計測から外す設定が、ブラウザによっては効かない所。後のほうはその日のうちに直した
- 時間：Codex の検証は、依頼を置いてから報告が書き終わるまで5分（18:32〜18:37）。人がしたのは「Codex に検証を頼んで」と言うことだけで、依頼書づくりと受け渡しは Claude と依頼箱（Claude Code への依頼を Mac の見張り係が自動で渡す仕組み）が行った

pixelstomotors.com は、ロボットとフィジカルAI（現実の物を動かす AI）の研究を、ひとりで記録して公開しているサイトです。人の来訪は1日20〜30表示ほどで、ページを自動で読みに回る機械（クローラー）はその10倍以上来ます。人と機械を分けるために、ページの中の小さなプログラムが「マウスを動かした・画面に触れた」などの人の操作があったかを記録しています（LOG451）。

11月12日の週の分析で、この人の表示が11日に3件、12日（19時まで）に2件しかないことに気づきました。それまでは平日に1日16〜30件ありました。Claude は計測のコードと実際の動きを確かめたうえで「故障ではない」と報告しましたが、そのあとの話の中で、Claude 自身の見立てが何度も揺れました。

> 一旦計測についてもう一度見直して、Codexに敵対的検証を依頼してください

敵対的検証は、合っていることを確かめるのではなく、穴を探す役を別の AI に任せるやり方です。同じ書き手が書いて確かめると同じ盲点を持つので、このプロジェクトではコードを変えたら外の AI に見てもらう決まりにしています。

| やったこと | なぜ | 結果 |
|---|---|---|
| 今週の3つの数字を見た | 週の分析 | 人の表示が11/11から急に減っていた |
| 計測のコードの変更・送信・ブロックを確かめた | 故障かどうかを見るため | 計測のコードは11/6から変わっていない。機械として数えられる記録は届く |
| Claude の読みを1件ずつの時刻で返せるようにした | 「試しが混ざっているかも」で止めていたため | 11/3 の12件はエイイチの試しと確定。残りはだれか分からない |
| Codex に敵対的検証を頼んだ | 結論の言い過ぎを探すため | 4つの結論のうち2つ撤回・1つ弱め・1つ範囲を限定 |
| 同じ曜日どうしで数え直し、Search Console と LinkedIn の投稿数を並べた | Codex が挙げた次の確認のため | 減ったのは主に「直接・不明」。Search Console の表示回数も11/10から落ちて見えるが、まだ途中の数 |
| 計測の除外設定の穴と、読み方の説明を直した | Codex の指摘 | 0時またぎの二重の数え方は未修正 |


下の図で、人の表示と同じ日のほかの数を切り替えて見られます。Claude の4つの結論と Codex の判定も、押すと理由が出ます。

【図解】LOG494_claims_and_days.html

## 作業ログ ― 週の分析から Codex の検証まで


### 11/9の週の3つの数字：AI に読まれる数は横ばいに見え、人の表示が急に減った

主に見る3つの数字（AI の利用者の依頼で読みに来た数・AI のサービスのリンクから来た人の数・サイト名の検索の数）を、計測の道具（kpi・site_usage・crawler_visits）で取りました。11/9（月）から11/12（木）の途中までの数です。

| | 11/9〜11/12 | 11/2〜11/5（同じ曜日） |
|---|---|---|
| AI の利用者の依頼で読みに来た数 | 24（ChatGPT 18・Claude 6） | 37 |
| AI のリンクから来た人 | 1 | 2 |
| 人の表示 | 53 | 92 |
| サイト名の検索 | 未記録 | 0（途中の数） |

人の表示は、日ごとに見ると11/9が28、11/10が20、11/11が3、11/12が2（19時まで）でした。最初の報告では「Claude の読みには、エイイチや Claude の試しが入っている可能性があります」と書き添えています。この一文が、あとで問題になりました。


### 人の表示が11/11に3件になった ― 最初に Claude が確かめたこと

計測の故障かどうかを、次の4つで確かめました。

1. **計測のコードの変更**：サイトのコード（GitHub の p2m-site）で、記録を送る部分（SiteMeasure.astro）と受け取る部分（worker/index.js の evRecord・evKind・guarded・sameSite）の最後の変更は11/6。11/10〜11/11 の変更は記事と病院の試算だけで、ページの共通の部品（レイアウト・ヘッダー）も変わっていなかった
2. **記録が届くか**：クラウドの Playwright（自動で動かすブラウザ）で、PC とスマホ（iPhone 13 のまね）から記事を開き、ページを隠したときに送る記録が受け付けられる（204）のを見た
3. **ブロックされていないか**：クラウドのサーバーから開いても、確認画面は出ずに 200 が返った
4. **機械と AI の読み**：機械の表示は1日300〜400件のまま、AI の読みも普段どおりだった

ここから Claude は「故障ではなく、来訪が本当に減った」と報告しました。あとで分かったとおり、2 の自動のブラウザは navigator.webdriver（自動で動いている印）が立つので、記録は「機械」として数えられます。人として数えられる道筋は、ここでは一度も確かめていません。

#### 記録が届くかを見た Playwright のスクリプト（t.js）

```javascript
const { chromium, devices } = require('playwright');
(async () => {
  const b = await chromium.launch();
  for (const opt of [{}, devices['iPhone 13']]) {
    const ctx = await b.newContext(opt); const p = await ctx.newPage();
    const errs = []; p.on('pageerror', e => errs.push(e.message)); p.on('console', m => { if (m.type()==='error') errs.push(m.text()); });
    const res = [];
    p.on('request', r => { if (r.url().includes('/api/ev')) res.push('req '+r.method()); }); p.on('response', r => { if (r.url().includes('/api/ev')) res.push(r.status()); });
    p.on('requestfailed', r => { if (r.url().includes('/api/ev')) res.push('failed '+r.failure().errorText); });
    await p.goto('https://pixelstomotors.com/record/day18', { waitUntil: 'load' });
    await p.mouse.move(100,100); await p.waitForTimeout(1500);
    await p.evaluate(()=>{Object.defineProperty(document,'visibilityState',{value:'hidden',configurable:true});Object.defineProperty(document,'hidden',{value:true,configurable:true});document.dispatchEvent(new Event('visibilitychange'));window.dispatchEvent(new Event('pagehide'));}); await p.waitForTimeout(2000);
    console.log(opt.userAgent ? 'phone' : 'pc', 'ev:', res, 'errors:', errs.slice(0,5));
    await ctx.close();
  }
  await b.close();
})();
```

#### t.js の出力

```
pc ev: [ 'req POST', 204 ] errors: []
phone ev: [ 'req POST', 204 ] errors: []
```

最初の1回は、ページを移る操作で記録を送らせようとして、送信の様子が取れませんでした（送信は出ていたが、Playwright の応答の記録に残らない形だった）。ページを隠す操作に変えた2回目が上の出力です。

#### サーバーから開いたときの返り（curl）

```
$ curl -sS -o /dev/null -w '%{http_code} %{size_download}\n' -A 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1' 'https://pixelstomotors.com/?p2m-notrack=1' --max-time 20
200 465845
$ curl -sS -o /dev/null -w 'ev POST no-origin: %{http_code}\n' -X POST https://pixelstomotors.com/api/ev -d '{}' --max-time 15
ev POST no-origin: 403
```

2つ目の 403 は、ほかのサイトからの送信を断る決まり（sameSite）が働いている印で、故障ではありません。


### 「直接・不明」の来訪の話は、エイイチの閲覧ではなかった

Claude は次に「先週の『直接・不明』には、エイイチの閲覧が入っていたかもしれない」と書きました。エイイチの返事は「いやないよ。ブロックしてるから」。エイイチのブラウザは `?p2m-notrack=1` で計測から外してあります。続けて、検索から来る人はもともと少なかったのでは、という指摘があり、数え直すと11/2〜11/12 の人の表示189件のうち、いちばん多いのは「直接・不明」82件で、Google は56件でした。重みの付け方を、Google 中心から「直接・不明」中心に直しています。


### Claude の読みを1件ずつの時刻で見られるようにした

AI に読まれる数の推移を報告したとき、Claude はまた「Claude の分は、エイイチや私の試しが入っている可能性があります」と書きました。エイイチは、何度も確かめるよう言ってきたのに毎回同じことを書いている、と指摘しました。

> これ調べられないの？毎回言うよね？何度もチェックさせているつもりだけど。

計測の記録（Cloudflare R2 の `cr/{日付}/`）には、1件ずつの時刻が入っていました。ただ、Claude が使う計測の道具（MCP の crawler_visits）は日ごとの合計しか返していません。そこで、クローラーを1つ指定したときに、1件ずつの時刻・ページ・結果を返すようにしました（worker/index.js の crStats に `hits` を足した）。

- ねらい：「混ざりうる」で止めずに、時刻をチャットの履歴と突き合わせて確かめる
- 変わったこと：crawler_visits に bot を指定すると、新しい順に200件まで、日本時間の時刻とページが返る
- 見込める効果：試しの分を数から外せる。ただし、読み切れなかった範囲がある日は最新の200件ではない（あとで Codex が指摘した）

返った時刻を、エイイチの claude.ai のチャットの履歴と突き合わせました。11/3 09:26〜09:29 の12件は、トップの「AIで読む」を Claude で試したチャット（LOG437）で、Claude が答えの出典に挙げたページと一致しました。残りの7回（ページ10件）は、該当するチャットが見つかりませんでした。

Claude は「11/8 に作業中の Claude がサイトを読んだのに、その日の記録は0件だったので、作業中の Claude の読みは記録に入らない。残りは外の人」と報告しました。エイイチは、表の7回を見て次のように答えています。

> 疑いあるのはこれだけなの？これだけならおれのはずないよ。もっとアクセスしているから

この「外の人」という言い切りも、Codex の検証で撤回することになります。


### Codex への依頼：4つの結論と計測の作りの穴を探させた

依頼書には、Claude が出した4つの結論と、それぞれの攻めてほしい点を書きました。Codex はネットにつながらない前提で、コードの写し・数字の写し・依頼書だけを読んで判断します。依頼書と数字の写しは、計測のコード（index.js・kpi.js・mcp.js・SiteMeasure.astro・wrangler.jsonc）の写しと一緒に、Mac の `PixelstoMotors/_measurement_review_20261112/` に置きました。

| 結論 | Claude が出したときの言い方 |
|---|---|
| 1 | 11/11 からの人の表示の急減は計測の故障ではなく、来訪が本当に減った |
| 2 | 減ったのは主に「直接・不明」で、Google からも減った |
| 3 | 11/3 以降の Claude の読みのうち、試しは11/3 の12件だけで、残りは外の人 |
| 4 | AI の依頼読みは横ばい（週55 → 61 → 4日で24） |

依頼箱には「Codex を起動して検証を任せることだけ。検証そのものはしない」という依頼を置きました。前の依頼（病院のシミュレーション、依頼157）が18:31 に終わり、18:32 に始まって18:37 に終わっています。


### Codex の判定：結論1と3は撤回、4は弱め、2は範囲を限れば言える

Codex の報告の最後の表を、そのまま載せます（報告の全文は下の節）。

| 結論 | 判定と採用すべき言い方 |
|---|---|
| 1：故障ではなく本当の減少 | **故障を否定した部分は撤回。** 『記録された操作あり表示は11/11に3件、11/12途中に2件。実減か選択的欠損かは未確定』 |
| 2：直接・不明とGoogleが減った | **記録上の11/11以降の減少に限定すれば可。** 週全体のGoogle大幅減や直接流入の実減とする言い方は弱める。異なる長さ・曜日・途中日の合計比較は避ける |
| 3：残り7回10ページは外部の人 | **外部帰属の断定を撤回。** 『自己試行と確認された11/3分を除き、7つの時刻群・非robots10取得は帰属未確認』。7依頼/7人とも確定しない |
| 4：AI依頼読みは横ばい | **55→61→途中24の観測値はそのまま可、横ばいは弱める。** 同期間・自己試行・取得単位・真正性を揃えるまでは傾向未確定 |

Claude が見落としていた点を、言い換えて並べます。

- **人として数えられる道筋を確かめていなかった。** 自動のブラウザの記録は「機械」になるので、204 が返っても、実際の人のブラウザ（Safari や LinkedIn・X のアプリの中のブラウザ）で記録が届くかの根拠にならない
- **スマホ幅の割合0%は、0件の意味ではなかった。** 計測の表は割合を四捨五入して出すので、645件のうち1〜3件あっても0%と出る。実際に11/12 の人の表示2件のうち1件はスマホ幅だった
- **AI の読みの数は、ページの数ではなく取得の回数。** 同じページを2回取れば2件、/llms.txt も入る。依頼の数や人数には直せない
- **0時をまたいで送り直された表示を、2日に1件ずつ数える。** 記録は届いた日の箱に入り、日ごとの集計はその日の中だけで同じ表示をまとめるため。Codex が実際の集計のコードを模擬のデータで動かして、二重になるのを確かめた
- **自分の閲覧を外す設定が、ブラウザによっては効かない。** 設定を覚える場所（localStorage）が使えないブラウザでは、`?p2m-notrack=1` を付けて開いても記録を送っていた
- **1件ずつの時刻（hits）は、読み切れなかった範囲がある日は最新の200件ではない。** 全部のクローラーの記録を古い順に読んで途中で打ち切るため


### 分析し直し①：同じ曜日どうしで比べると、減ったのは「直接・不明」だった

Codex は、長さも曜日も違う期間の合計を比べるのをやめるよう指摘しました。計測の表（ev-stats）を「その日以降」で日ごとに取り、隣の日との差から1日ずつの数を出しました（スクリプトと出力は下の節）。

| 日 | 人の表示 | Google から | 直接・不明 | サイト内 | 機械の表示 | 不明（操作なし） |
|---|---|---|---|---|---|---|
| 11/2（月） | 30 | 5 | 20 | 2 | 250 | 6 |
| 11/3（火） | 25 | 4 | 12 | 7 | 243 | 10 |
| 11/4（水） | 16 | 8 | 7 | 0 | 349 | 5 |
| 11/5（木） | 21 | 4 | 12 | 3 | 340 | 10 |
| 11/6（金） | 29 | 12 | 7 | 4 | 309 | 4 |
| 11/7（土） | 10 | 3 | 5 | 1 | 325 | 10 |
| 11/8（日） | 5 | 1 | 4 | 0 | 365 | 2 |
| 11/9（月） | 28 | 8 | 4 | 12 | 383 | 9 |
| 11/10（火） | 20 | 9 | 9 | 2 | 319 | 6 |
| 11/11（水） | 3 | 1 | 1 | 0 | 374 | 1 |
| 11/12（木・19時まで） | 2 | 1 | 1 | 0 | 313 | 2 |

月〜水で比べると、人の表示は71 → 51、Google から17 → 18、直接・不明39 → 14でした。Google から来た数は月火ではむしろ増えていて、11/11 の1日だけ落ちています。直接・不明は、11/9 からすでに少なくなっていました。機械の表示は842 → 1,076 と増えていて、操作のない表示（不明）も21 → 16 で大きくは変わっていません。

11/11〜11/12 の人の表示5件のうち、スマホ幅は少なくとも1件ありました。「スマホが0になった」という手がかりは、四捨五入の見え方でした。


### 分析し直し②：Search Console の表示回数も11/10 から落ちて見える（まだ途中の数）

Codex は、計測の外の数と比べるよう挙げていました。Google の Search Console は、Google の検索結果にサイトが出た回数（表示回数）とクリックを Google の側で数えるので、サイトの中のプログラムが動かなくても数が残ります。

| 日 | クリック | 表示回数 | 自前の計測の Google から |
|---|---|---|---|
| 11/4 | 2 | 96 | 8 |
| 11/5 | 6 | 133 | 4 |
| 11/6 | 5 | 98 | 12 |
| 11/7 | 1 | 70 | 3 |
| 11/8 | 4 | 95 | 1 |
| 11/9 | 6 | 148 | 8 |
| 11/10 | 2 | 21 | 9 |
| 11/11 13:00〜11/12 の24時間 | 0 | 3 | ― |

表示回数は1日70〜150回あったものが、11/10 は21回、直近24時間は3回でした。ただし Search Console の数は2〜3日遅れて確定し、画面の最終更新は6時間前でした。11/10 のクリックが2回なのに、自前の計測では Google から9件来ているので、11/10 の数はまだ途中だと見ています。**表示回数が本当に落ちたのなら、サイトの中の計測とは関係なく Google の側で見つかりにくくなったことになる**ので、確定した数を11/15 以降に見直します。

自前の計測の「Google から」と Search Console のクリックは、もともと合っていません（11/6 は12件と5回）。Google の別の場所（画像検索・Discover・Google アプリなど）からも www.google.com として来るためと考えていますが、確かめてはいません。


### 分析し直し③：「直接・不明」の減り方は、LinkedIn の投稿を1日4本から1本にした時期と重なる

「直接・不明」には、リンク元を送らないアプリ（LinkedIn や X のアプリ、メール）から開いた人が入ります。11/9 に LinkedIn の投稿を、1日4本から平日に1日1本へ組み直していました（LOG478）。自動投稿の記録から、日ごとに出した本数を数えました。

| 日 | LinkedIn に出した本数 | 直接・不明 |
|---|---|---|
| 11/4 | 4 | 7 |
| 11/5 | 4 | 12 |
| 11/6 | 4 | 7 |
| 11/7 | 3 | 5 |
| 11/8 | 2 | 4 |
| 11/9 | 2 | 4 |
| 11/10 | 1 | 9 |
| 11/11 | 1 | 1 |
| 11/12 | 1 | 1 |

11/2〜11/12 の人の表示には、LinkedIn に出した4コマ（/manga/ep126〜131）と課題地図（/issues/liability-demarcation・/issues/tacit-knowledge-capture）が1〜2件ずつ入っていて、出した投稿と同じページです。マンガは11/10 から LinkedIn に出していません。本数と「直接・不明」は同じ向きに減っていますが、11/10 は1本で9件あり、ぴったりとは合いません。LinkedIn が「直接・不明」の大きな部分だったという見方は、今の数では「重なる」までです。


### 分析し直し④：AI の依頼読みは、同じ曜日で比べると34 → 21

| | 11/2〜11/4 | 11/9〜11/11 |
|---|---|---|
| AI の依頼読み（取得の回数） | 34 | 21 |
| 11/3 の試し12件を除くと | 22 | 21 |

試しを除くと、同じ曜日どうしでほぼ同じでした。ただし数えているのは取得の回数で、1回の質問で何ページ読んだかが違えば数も変わります。「横ばい」とは言わず、観測した回数として残します。


### 直したコード：自分の閲覧を外す設定と、計測の読み方の説明

Codex の指摘のうち、すぐに直せて影響の小さい2つを直しました（commit 8af4e01）。

- ねらい：自分の閲覧が人の数に混ざる穴をふさぐ。Claude が次の分析で同じ言い過ぎをしないよう、読み方の説明を検証の結果に合わせる
- 変わったこと：`?p2m-notrack=1` で開いた表示は、設定を覚えられないブラウザでも送らない。読み方の説明に「依頼読みは取得の回数」「作業中の Claude の読みが記録に入るかは未確認」「日ごとの集計は作ったあとの記録が入らず、0時またぎを二重に数えることがある」を書いた
- 見込める効果：自分の閲覧が混ざる分が減る（どれだけ減ったかは数えられない）。次の週の分析で、試しや外の人を言い切らなくなる

0時をまたぐ二重の数え方と、1件ずつの時刻の打ち切りは、集計の作り（日付の決め方・まとめる範囲）を変える必要があるので、まだ直していません。


### まだ決まっていないこと：人の表示の急減は、実機の1件を端から端まで追うまで決められない

Codex が挙げた、急減の原因を決めるための確認を、この記事の時点の状態と並べます。

| 確認 | 状態 |
|---|---|
| 日本の家庭や携帯の回線で、実物の Safari と、LinkedIn・X のアプリの中のブラウザから1件開き、記録が「人」として残るまでを追う | 公開のあと、LINE の中のブラウザで1件行い、「人」として残った（下の追記）。Safari と LinkedIn・X はまだ |
| 11/10 前後に Cloudflare の設定（ボット対策・WAF・チャレンジ）や配信が変わっていないかを見る | まだ。計測のコードとサイトの共通の部品は変わっていない |
| 元の記録を日付と範囲を固めて数え直し、Search Console の確定値と比べる | 日ごとの数え直しはした（上の表）。Search Console は11/15 以降に確定値を見る |

いま言えるのは、記録に残った人の操作のある表示が11/11 に3件、11/12（19時まで）に2件だったことと、同じ時期に「直接・不明」が先に減り、Search Console の表示回数も途中の数では落ちて見えることまでです。来訪が本当に減ったのか、人の記録だけが落ちているのかは、まだ分けられていません。



### 追記（19:14）：LINE の中のブラウザから開いた1件は「人」として記録された

公開のあと、Codex が挙げた確認の1つ目を、エイイチのスマホで行いました。印（utm_source=p2mtest1112）を付けた住所を、スマホの LINE の自分だけのトークに貼ってタップし、LINE の中のブラウザで開いて少しスクロールしてから、ホーム画面に戻ってもらいました。最初は LinkedIn のアプリで自分あてのメッセージに貼ろうとしましたが、LinkedIn では宛先に自分を選べなかったので、同じくアプリの中のブラウザで開く LINE に替えています。

開いた住所：https://pixelstomotors.com/record/day18?utm_source=p2mtest1112

計測の表（ev-stats・11/12 から）を、人・機械・不明に分けて取ると、印の付いた1件は「人」のほうにだけありました。

| 分け | 印 p2mtest1112 の表示 | 11/12 の表示 | スマホ幅の割合 | /record/day18 |
|---|---|---|---|---|
| 人（操作あり） | 1 | 3（開く前は2） | 67% | 1件・13秒・半分まで読んだ |
| 機械 | 0 | 322 | 1% | 6件（Claude の Playwright の確認を含む） |
| 不明（操作なし） | 0 | 2 | 50% | 0件 |

人の表示3件のうち2件がスマホ幅になったので、開いた1件はスマホ幅として数えられています。**スマホのアプリの中のブラウザから来た人の記録は、実機の1件では落ちずに「人」として残った。** 確かめたのは LINE とエイイチのスマホの1件だけで、Safari・LinkedIn や X のアプリの中のブラウザ・ほかの人の端末は見ていません。人の記録だけが落ちる経路が全部否定されたわけではありませんが、11/11 からの減少が本当の来訪の減少である側の根拠が1つ増えました。

#### 確かめに使ったコマンドと出力（2026-11-12 19:15）

```
$ K=$(tr -d ' \n\r' < "$HOME/mnt/KIOXIA/p2m_stats_key.txt"); for w in human bot unknown; do curl -s --max-time 60 -H "Authorization: Bearer $K" "https://pixelstomotors.com/api/ev-stats?format=json&since=2026-11-12&who=$w" | python3 -c "
import json,sys;d=json.load(sys.stdin);w=d['byWeek'][0] if d['byWeek'] else {}
print('$w', 'utm:',[u for u in d['utmSources'] if 'p2m' in u['source']], 'views',w.get('views'),'sp%',w.get('spPct'), 'day18:',[p for p in d['byPage'] if p['path']=='/record/day18'])"; done
human utm: [{'source': 'p2mtest1112', 'count': 1}] views 3 sp% 67 day18: [{'path': '/record/day18', 'views': 1, 'medianSeconds': 13, 'read25Pct': 100, 'read50Pct': 100, 'read75Pct': 0, 'read100Pct': 0, 'deadClicks': 0, 'rageClicks': 0, 'copies': 0, 'videoPlays': 0, 'outClicks': 0}]
bot utm: [] views 322 sp% 1 day18: [{'path': '/record/day18', 'views': 6, 'medianSeconds': 2, 'read25Pct': 0, 'read50Pct': 0, 'read75Pct': 0, 'read100Pct': 0, 'deadClicks': 0, 'rageClicks': 0, 'copies': 0, 'videoPlays': 0, 'outClicks': 0}]
unknown utm: [] views 2 sp% 50 day18: []
```

この印の付いた1件は試しの表示なので、これからの人の数の分析では外して数えます。

### Codex への検証の依頼書（codex_verification_request.md）

````markdown
# 敵対的検証の依頼：pixelstomotors.com の計測と、2026-11-12 の分析の結論

あなたの役目は、Claude が出した結論と計測の作りの**穴を探すこと**です。「合っている」と確かめるのではなく、「どこが間違っている可能性があるか」「どの結論が根拠より強く言い過ぎているか」を見つけてください。

このフォルダの中身：
- `code/` … 計測のコードの写し（p2m-site の HEAD は `code/HEAD.txt`）。`index.js`（Cloudflare Worker 本体。/api/ev・/api/cr-stats・/api/ev-stats・クローラーの記録）、`kpi.js`（3つの数字の日ごとの集計）、`mcp.js`（Claude が使う計測ツールと「読み方」の説明）、`SiteMeasure.astro`（ブラウザ側の記録）、`wrangler.jsonc`、`measurement_git_log.txt`（10/20 以降の関係する変更）
- `data_snapshot.md` … 計測ツールから写した数字と、Claude が行った確認

読むだけです。書いてよいのは報告ファイルだけ。ネットにはつながらない前提で、コードと数字だけで判断してください（実際のサイトや Cloudflare の設定は見られません。見られないことで判断できない点は「判断できない」と書く）。

---

## サイトと計測の前提

- pixelstomotors.com は個人の研究記録サイト（Astro の静的ページ + Cloudflare Worker）。人の来訪は1日20〜30表示ほど、機械（クローラー）は1日300〜400表示
- 計測は2系統
  - **ev**：ページの中の JS（SiteMeasure.astro）が、ページが隠れたときに /api/ev へ送る。人の操作（pointermove・pointerdown・touchstart・wheel・keydown）が1回でもあれば `u=1`。Worker の `evKind` が b（機械）／h（人の操作あり）／x（操作なし）に分ける。R2 の `ev/{日付}/` に残る
  - **cr**：Worker がページ・テキストを返すとき、名乗り（User-Agent）が一覧（CRAWLERS）に当たれば R2 の `cr/{日付}/` に残す
- 見る数字は3つ（kpi.js）：AI の依頼読み（ChatGPT-User・Claude-User など）／AI のリンクから来た人（人の操作ありの表示だけ）／サイト名の検索（Search Console を手で記録）
- エイイチ自身の閲覧は `?p2m-notrack=1`（localStorage）で外している

---

## 検証してほしい結論（Claude が 2026-11-12 に出したもの）

### 結論1：11/11 からの人の表示の急減（1日20〜30 → 3・2）は計測の故障ではなく、来訪が本当に減った
根拠：計測のコードは 11/6 以降変わっていない／Playwright で PC・スマホから送った記録が 204 で受け付けられた／機械の表示と AI の依頼読みは普段どおり／サーバーからでもチャレンジは出なかった。

攻めてほしい点：
- 1a. 人の表示だけが落ち、機械の表示は落ちていない。**計測の故障で、人の分だけが落ちる経路**はないか。コードから考えられるものを全部挙げる。例：
  - `sameSite()` が Origin・Sec-Fetch-Site で弾く条件（Origin が `null` になるブラウザ・設定、sendBeacon の Origin、Safari・アプリ内ブラウザ）
  - `evKind` の `request.cf.verifiedBotCategory` や `botManagement.verifiedBot` が、人のブラウザで真になることはあるか
  - `EV_BOT_UA` / `AUTO_UA` に、普通のブラウザやアプリ内ブラウザ（LinkedIn・X・Google アプリなど）の名乗りが当たることはないか（`preview`・`bot;` など）
  - 流量制限（`guarded` の ratelimits）が、人のほうだけを弾く形になりうるか
  - `u`（人の操作）が付かず x になる読み方（スマホで触れずに読む、PC でキーもマウスも動かさない）
- 1b. 11/11〜11/12 の全部の表示 645件のうち、スマホ幅が 0% だった。これは結論1と矛盾しないか。人の表示が5件しかないことで説明がつくか、それとも別の故障を示しているか
- 1c. Playwright（Chromium、クラウドの IP）で 204 が返ったことは、実際の人（日本の家庭・携帯回線、Safari、アプリ内ブラウザ）で記録が届くことの根拠としてどこまで足りるか。足りないなら、何を確かめれば足りるか
- 1d. コードの外（Cloudflare の設定：Bot Fight Mode、WAF、チャレンジ、キャッシュ、Workers のルート）が 11/11 に変わって、人だけが弾かれた・ページは見えたが JS が動かなかった、という可能性を、data_snapshot の数字はどこまで否定できるか

### 結論2：減ったのは主に「直接・不明」（1日約10 → ほぼ0）で、Google から（1日約5、11/10 は約11）も減った
- 2a. 11/2〜11/8 と 11/9〜11/12 の数の比べ方（期間の長さ・曜日・途中の日）に誤りはないか
- 2b. 「直接・不明」と Google が同じ日に落ちたことから、何が言えて、何が言えないか

### 結論3：11/3 以降の Claude-User の読みのうち、エイイチ・Claude の試しは 11/3 の12件だけで、残り7回（10ページ）は外の人
根拠：11/3 の分はチャットの出典と一致。11/8 に Claude Code のセッションが WebFetch でページを読んだのに、その日の Claude-User は0件だったので、Claude の作業のセッションは Claude-User に入らないとした。エイイチは「自分ならもっと多く読む」と言っている。
- 3a. 11/8 の1回の観察から「Claude Code の WebFetch は Claude-User に入らない」と一般化してよいか。その WebFetch が別の名乗りで来て記録されなかった／キャッシュから返った／別のドメインを読んだ、などの可能性
- 3b. Claude-User は Cloudflare が本物かを確かめていない（`ok` が 0）。名乗りを偽った機械が混ざる可能性と、その見分け方
- 3c. 名乗りの当て方（`crawlerOf` が CRAWLERS を順に `includes` で見る）で、Claude-User・ChatGPT-User・Perplexity-User が別の名前に化ける、または逆に別のものがこれらに化けることはないか

### 結論4：AI の依頼読みは横ばい（週 55 → 61 → 今週4日で24）
- 4a. kpi.js の数え方（robots.txt を外す、ChatGPT-User の未確認を外す、1ページ1件）で、同じ1回の依頼が何ページも読むと数が膨らむ。「横ばい」の判断にこれがどう効くか
- 4b. 日ごとの集計を一度作ると残す作り（`kpi/{日付}.json`）で、作ったあとに届いた記録が抜ける・二重に数える、ということはないか（日付をまたいで送り直された ev、5分ごとの scheduled の時刻）

---

## 計測の作りとして見てほしいこと

- 5a. 人の数（h）の決め方は、「人が読んだ」を数えるのに足りているか。過小・過大のどちらに偏るか
- 5b. ev の送り直し（同じ v で n を増やす）の重ね方（kpi.js は n が最大の1件、index.js の evStats はどうか）が、両方で同じか
- 5c. `/api/cr-stats` の打ち切り（40ページ×1000件）と、今回 `bot` を指定したときに足した `hits`（新しい順に200件）の作り（index.js の crStats）に誤りはないか
- 5d. ここまでで「計測の故障」と疑わしいもの、または今後の分析を誤らせるものがあれば、優先度順に

---

## 報告の形

`codex_report_20261112.md` としてこのフォルダに書く。

各項目（1a〜5d）に：
- ✅ OK（結論・作りのとおりでよい）
- ⚠️ 要注意（言い過ぎ、または確かめが足りない。何をどう確かめれば決着するか）
- ❌ NG（誤り。該当するファイルと行番号、直し方）

最後のサマリ：
1. 結論1〜4のうち、このまま言ってよいもの／言い方を弱めるべきもの／撤回すべきもの
2. 11/11 の急減の原因を決着させるために、次にいちばん先にやるべき確認（3つまで、優先順）
3. 計測のコードで直すべきもの（あれば、優先順）
````


### Codex に渡した数字の写し（data_snapshot.md）

````markdown
# 計測の数字の写し（2026-11-12 16:00 ごろ、計測ツール kpi / site_usage / crawler_visits から）

日付は日本時間。週は月曜はじまり。11/12 は途中の数。

## 日ごとの数（kpi）

| 日 | 人の表示 (humanViews) | 外から入った人の表示 | AI の依頼読み (aiReads) | うち ChatGPT-User | うち Claude-User | AI のリンクから来た人 |
|---|---|---|---|---|---|---|
| 10/26 | 52 | – | 9 | 8 | 1 | 0 |
| 10/27 | 17 | – | 13 | 13 | 0 | 0 |
| 10/28 | 21 | – | 4 | 4 | 0 | 0 |
| 10/29 | 33 | – | 4 | 4 | 0 | 0 |
| 10/30 | 10 | – | 17 | 16 | 1 | 0 |
| 10/31 | 18 | – | 6 | 5 | 1 | 0 |
| 11/1 | 13 | – | 2 | 2 | 0 | 0 |
| 11/2 | 30 | 28 | 7 | 7 | 0 | 1 |
| 11/3 | 25 | 18 | 22 | 10 | 12 | 1 |
| 11/4 | 16 | 16 | 5 | 5 | 0 | 0 |
| 11/5 | 21 | 18 | 3 | 3 | 0 | 0 |
| 11/6 | 29 | 25 | 5 | 5 | 0 | 0 |
| 11/7（土） | 10 | 9 | 13 | 9 | 4 | 1 |
| 11/8（日） | 5 | 5 | 6 | 6 | 0 | 0 |
| 11/9 | 28 | 16 | 2 | 2 | 0 | 0 |
| 11/10 | 20 | 18 | 6 | 5 | 1 | 0 |
| 11/11 | **3** | **3** | 13 | 10 | 3 | 1 |
| 11/12（16時まで） | **2** | **2** | 3 | 1 | 2 | 0 |

## 人の表示の来た所（site_usage, who=human）

| 期間 | 合計 | Google | 直接・不明 | サイト内 | その他 |
|---|---|---|---|---|---|
| 11/2〜11/8 | 136 | 37 | 67 | 17 | LinkedIn など |
| 11/9〜11/12 | 53 | 19 | 15 | 14 | LinkedIn 2・keep.google 2・chatgpt 1 |
| 11/10〜11/12 | 25 | 14 | – | – | – |
| 11/11〜11/12 | 5 | 3 | – | – | t.co 1・chatgpt 1 |

- 11/11〜11/12 の全部の表示（人・機械・不明）は 645 件。うち機械 638・人 5・不明 2。スマホ幅（sp）の割合は 0%（11/2〜11/8 の人の表示では 21%）
- 機械の表示は 1日 300〜400 件で、11/11 以降も変わらない
- 11/2〜11/8 の「不明（操作なし）」47 件、11/9〜 17 件

## Claude-User の1回ずつの訪問（crawler_visits bot=Claude-User の hits。robots.txt を含む）

```
2026-11-12 13:18:00 /            ; 13:18:00 /robots.txt ; 13:17:59 /
2026-11-11 14:05:22 /message
2026-11-11 13:46:10 /            ; 13:46:10 /robots.txt ; 13:46:10 /
2026-11-10 21:08:38 /record/making-explainer-video-with-ai ; 21:08:37 /robots.txt
2026-11-07 18:15:34 /record/making-explainer-video-with-ai
2026-11-07 11:37:37 /series2     ; 11:37:37 /robots.txt
2026-11-07 07:53:48 /record/day78 ; 07:53:48 /robots.txt ; 07:53:47 /
2026-11-03 09:26:19〜09:29:39  /llms.txt?via=claude と記事11本（+ robots.txt）
```

## Claude が行った確認（2026-11-12）

1. 計測にかかわるコード（worker/index.js の evRecord・evKind・guarded・sameSite、SiteMeasure.astro）の最後の変更は 11/6。11/10〜11/12 の変更は記事・試算・トップの見た目だけ（code/measurement_git_log.txt）
2. クラウドの Playwright（Chromium）で、PC と iPhone 13 のエミュレーションから記事を開き、ページを隠す操作をして /api/ev への POST が 204 で受け付けられるのを確かめた。ページのエラーなし。navigator.webdriver が立つので機械として数えられる
3. クラウドのサーバーから curl で開いても、確認画面（チャレンジ）は出ず 200
4. 11/3 09:26〜09:29 の Claude-User 12件は、エイイチが claude.ai で TOP の「AIで読む」を試したチャット（LOG437）の出典と記事が一致
5. 11/8 に Claude Code のセッションが WebFetch で /serving-robot-one-less-staff を読んだが、11/8 の Claude-User は 0 件。ここから「Claude の作業のセッションの WebFetch は Claude-User に入らない」とした
6. エイイチは自分のブラウザの閲覧を計測から外している（本人談）。11/3 以降の Claude-User の未確認の7回について、本人は「自分ならもっと多く読むので、自分ではない」と言っている
````


### 依頼箱に置いた依頼（20261112_159）

````markdown
---
作業フォルダ: /Users/shimazueiichi/r2r2r-scripts
上限時間: 90
---
# Codex に、サイトの計測と 11/11 からの人の急減の結論の敵対的検証を頼む

あなた（Claude Code）の仕事は **Codex を起動して検証を任せることだけ**。検証そのものはしない。どのファイルも変更しない（r2r2r-scripts も含む）。

## 手順

1. Codex CLI があるか確かめる：`command -v codex || ls ~/.npm-global/bin/codex`。見つからない・ログインが切れている場合は、何もせずに止めて、報告の「決めてほしいこと」にその旨を書く。
2. 次のコマンドで Codex に渡す（そのまま実行。検証依頼書の中身はあなたが要約・書き換えしない）：

```bash
REVIEW_DIR="$HOME/Library/Mobile Documents/com~apple~CloudDocs/デスクトップ/ADAPT DESIGN/じぶんの/PixelstoMotors/_measurement_review_20261112"
find "$REVIEW_DIR" -type f -exec brctl download {} \; 2>/dev/null
codex exec --skip-git-repo-check -C "$REVIEW_DIR" -s workspace-write \
  "codex_verification_request.md を読んで、その指示どおりに検証し、報告を codex_report_20261112.md としてこのフォルダに書いてください。code/ と data_snapshot.md は読むだけで、書いてよいのはこの報告ファイルだけです。" \
  > "$REVIEW_DIR/_codex_run_20261112.log" 2>&1
```

3. 終わったら `codex_report_20261112.md` ができたか確かめる。
   - できていれば、報告には「できた」とそのパスと、最後のサマリ節だけを写す。
   - できていなければ、`_codex_run_20261112.log` の末尾 40 行を報告に写す。

## 守ること

- Codex の報告の中身をあなたが評価・手直ししない。
- `-s workspace-write` を外さない・制限を外す指定を足さない。
- 失敗しても自分で検証を代わりにやらない。

報告の最後は「判定：合格／止めた（決めてほしいことあり）／失敗」のどれか1つで終える。
````


### Codex の報告の全文（codex_report_20261112.md）

````markdown
# pixelstomotors.com 計測・分析の敵対的検証

検証日：2026-11-12。対象 HEAD：`1e04e85`（写しの `code/HEAD.txt`）。

## 検証の範囲と結論

依頼書、`data_snapshot.md`、`code/` の全ファイルを対象に静的検証した。ネット接続、本番への送信、本番設定の照会は行っていない。Playwright・curl・チャット履歴の確認は、提供された記述であり、今回独立に再現した事実ではない。行番号はこのフォルダの写しに対応する。

**確認できたのは「h に分類されて届いた表示が急減した」ことまで。実際の来訪減と計測欠損は切り分けられていない。** 外部の人による Claude 利用という帰属も確定できない。コードには日跨ぎ再送の重複・集計範囲の不一致があり、スマホ 0% には整数丸めという別の落とし穴がある。ただし、これらが11/11の急減を引き起こした証拠はない。

補助検証はファイルを作らず Node.js のメモリ内で実施した。実際の `kpi.js` の `computeKpiDay` を模擬 R2 に対して実行し、同じ v の日跨ぎ記録が各日に1件ずつ数えられることを確認した。割合の丸め・週合計も再計算した。コード・元データは変更していない。

## 1. 人の表示の急減

### 1a. 人だけが落ちる経路 — ⚠️ 要注意

次の経路をコードから排除できない。いずれも「存在する経路」であり、今回発生したという意味ではない。

| 段階 | 人の表示が欠ける条件・影響 | 根拠 |
|---|---|---|
| 記録を開始しない | DNT=1、GPC=true、localStorage の notrack=1。実際の人でも ev 全体が送られない。共有された notrack 付きリンクでも設定される | SiteMeasure.astro:29–37,50 |
| JS が起動しない | 計測スクリプト未配置、ビルド・配信不一致、JS無効、ブロッカー、CSP、古いHTMLとアセットの不整合、ロード失敗・構文/API実行エラー | SiteMeasure.astro:23以降、wrangler.jsonc の assets 設定。生成物・ヘッダーは未提供 |
| 送信契機が来ない | 初回ロード時には送らず hidden/pagehide 待ち。読んだままのタブ、プロセス強制終了、通信断などは未記録または遅延 | SiteMeasure.astro:203–220 |
| 送信失敗を回収しない | Beacon の true はサーバー保存の確認ではない。403/429/ネット失敗でも n を増やし dirty=false。例外時も同様。fetch はステータス未確認で、Beacon が例外を投げた場合は fallback 自体を実行しない | SiteMeasure.astro:209–214 |
| sameSite 拒否 | Origin が文字列 `null` なら URL 解析失敗で403。Origin欠落かつ Sec-Fetch-Site が same-origin 以外・欠落でも403。Origin が存在すれば Fetch-Site による救済なし | index.js:130–139 |
| 制限 | IP 単位で RL_EVENT を共有し ev と hk-event が競合。携帯・組織の共有IP、多数タブ等で429。cf-connecting-ip欠落なら unknown に集中 | index.js:110–111,140–145、wrangler.jsonc の60回/60秒 |
| 人を b に分類 | CF判定がtruthy、UA空、広い正規表現、wd/hl=1 のいずれかで u=1 より優先 | index.js:365–372 |
| 人を x に分類 | 操作なし閲覧、計測起動前の操作、iframe 内だけの操作、支援技術等で列挙イベントが親documentに届かない | SiteMeasure.astro:79–85,165–178 |
| サーバー・集計 | R2 put失敗、古いKPI、一覧打ち切り・期間差でも見かけが変わる | index.js:405,425–435、kpi.js:96–107 |

通常の同一オリジン送信が常に Origin=null になる、Safariやアプリ内ブラウザが一般に失敗する、とまでは言えない。対象ブラウザの実際のリクエストヘッダーが必要。`sameSite` は scheme を比較せず host のみを比較する点でも「同一origin」の厳密判定ではない。修正時は許可 origin を明示し、null を無条件許可しない。

CFの verified 判定が普通の人で真になる頻度や仕様上の保証は資料にない。真なら人の操作より優先して b になることは確実だが、実際の誤判定は判断できない。判定理由別の件数を確認する必要がある。

UA の `LinkedIn`、`Twitter`、`GSA` という文字列だけでは該当しない。一方 `preview` は境界なし、`bot;`・独立語bot・`okhttp`等は利用者向けアプリのUAに含まれれば該当する。SNSプレビュー自体は機械なので妥当であり、人のアプリ内閲覧と混同しない。実UAとヒットした規則を短期診断しなければ誤分類の有無は決められない。

機械の ev が継続しても、実ユーザー固有の送信経路・プライバシー設定・分類を保証しない。cr はJSもsameSiteもRL_EVENTも通らない別経路なので、cr正常はさらに弱い根拠である。x が2件しかないことは大量の h→x だけで説明する説には不利だが、未送信や h→b は否定しない。

### 1b. 645件のスマホ幅 0% — ⚠️ 要注意

**0% は0件を意味しない。** `index.js:475–480` は `Math.round(sp/views*100)`。分母645なら sp が1、2、3件でも0%。原数またはhumanだけの sp/views を取る必要がある。さらに `spPct` は who で絞った母集団だが humanViews/botViews は絞る前（index.js:460–482）。同じ行に出ても分母が違うことがある。期間・who・truncated の実レスポンスが未提供なので、645と割合が同一母集団かも再確認が必要。

仮に人5表示すべてが本当にpcでも、従来のsp比率21%を固定し独立と仮定すると、5件でspが0件の確率は `0.79^5 ≈ 30.8%`。珍しい証拠ではない。表示は同一人で相関しうるため、これは参考計算である。機械638表示に人の21%を適用してはいけない。

また sp は初期 innerWidth<600 の意味で端末種別ではない（SiteMeasure.astro:76）。viewport設定欠落ならスマホでもpcになりうるが、HTMLは未提供。スマホ消失・故障の証拠にも、故障否定の証拠にも現状では足りない。

### 1c. Playwrightの204 — ⚠️ 要注意

204は、その環境・その送信について Worker が R2 put を await して終了した証拠になる（index.js:403–406）。ただし集計への反映と h 判定は別。webdriver により b なので、h の経路の成功を直接確認していない。iPhoneエミュレーションは実Safari/WebKitや実携帯回線の検証ではない。

決着には、日本の家庭回線と携帯回線で、実Safariおよび代表的なアプリ内ブラウザから自然な操作を行い、HTML・計測JSの取得、例外、Origin/Fetch-Site、POST応答、対応する v のR2保存、k=h・w・n、集計反映まで一続きで確認する。テスト記録は識別可能にして通常分析から区別する。notrack/DNT/GPC状態も記録する。

### 1d. Cloudflare等のコード外変更 — ⚠️ 要注意

資料から否定できるのは全面停止だけ。WAF・チャレンジ・Bot対策はUA/IP/地域/パス等で差が生じうるし、ページGETが成功してもJSアセットやPOSTが失敗しうる。クラウドからの200は日本の実ユーザーへの配信を代表しない。

`measurement_git_log.txt` は関連変更の抜粋で、11/8の見た目変更と11/12の統計・説明変更を含む。履歴の記述は計測の主要部分が変わっていないという補助証拠にとどまり、デプロイ済み成果物・CF管理画面・ルート・ヘッダー等の不変性を証明しない。11/10〜12の全差分もここにはない。本番の変更履歴と11/10前後の応答・配信物比較が必要であり、現時点では判断できない。

## 2. 流入元の減少

### 2a. 期間・曜日・途中日の比較 — ⚠️ 要注意

| 指標 | 11/2〜8：7日 | 11/9〜12：3日＋16時間 | 後半を単純に4日で割った値 |
|---|---:|---:|---:|
| 人の表示 | 136（19.43/日） | 53 | 13.25/日 |
| Google | 37（5.29/日） | 19 | 4.75/日 |
| 直接・不明 | 67（9.57/日） | 15 | 3.75/日 |
| サイト内 | 17（2.43/日） | 14 | 3.50/日 |

53/136 だけで減少率を語れない。後半は平日のみ、前半は週末を含む。経過時間3.667日で割れば人14.45/日、Google5.18/日、直接4.09/日だが、時刻別流量が一定ではないので機械的外挿も推奨しない。Googleの期間平均は大幅減を示していない。

差分では11/9はGoogle5件、11/10は11件、11/11〜12は計3件。11/11〜12は合計5件が Google3・t.co1・chatgpt1で尽きるため、その範囲の直接・不明0件は資料上整合する。11/9〜10の直接・不明は計15件。『11/11以降、記録されたGoogleと直接・不明が少ない』とは言えるが、同じ長さ・曜日・締め時刻で再比較する必要がある。

### 2b. 同時に落ちた意味 — ⚠️ 要注意

記録上、複数の流入元にまたがる減少とは言える。Googleだけの検索順位変化では直接・不明まで落ちた理由を自動的には説明できない。しかし共通するJS・送信・分類の障害も、実際の需要減も説明候補であり、同時減でどちらかには決められない。

『直接・不明』はアプリ・referrer抑制・ブックマーク等が混ざる残余区分で、固定した読者層ではない（SiteMeasure.astro:55–70、index.js:495–497）。日単位の原数・端末別・ページ別を確認し、Search Consoleクリックやページ配信数と照合する。Search Consoleも表示回数と同義ではなく時差・確定遅れに注意する。

## 3. Claude-Userの帰属

### 3a. WebFetchの一般化と外部利用の断定 — ❌ NG

11/8にClaude-Userが0件だったことから、全Claude Code/WebFetchが将来も含めてClaude-Userに入らず、Claude-Userはclaude.aiだけ、と一般化できない。`code/mcp.js:28` は根拠より強い断定で、削除して『11/8の当該観察では記録を対応付けられなかった。経路と利用者は未確定』とする。

キャッシュ、別UA、リダイレクト先・別ドメイン、実アクセス未発生、取得失敗、cr保存失敗、集計打ち切り、タイムゾーンの取り違え等が未排除。`notrack` はブラウザのev設定であり、AI側のcrを除外しない。本人の『自分ならもっと読む』も帰属を決める証拠ではない。

11/3の12件はチャット出典一致という強い自己試行の根拠が報告されているが、こちらで履歴を独立確認していない。残る7つの時刻のまとまり・非robots10リクエストは**帰属未確認**とする。時刻のまとまりは7人・7依頼を意味しない。既知の各クライアントから一意なテストURLで取得し、キャッシュ有無・リダイレクト・生アクセス記録と対応させても、そのテスト条件内での確認にとどまる。

### 3b. ok=0と偽装 — ⚠️ 要注意

UAは自己申告であり偽装可能。ok=0は本物でないと確定した意味でも、Claudeが原理的に検証対象外と証明する意味でもない。コードはCF一般のbot判定を記録するだけ（index.js:571–580）で、Claudeという名乗りと検証済み主体の一致を検査しない。疑わしいリクエストもClaudeはKPIに入る（kpi.js:63–66）。

時刻・読んだページ・robotsの順序だけでは真正性も外部利用も確定しない。追加調査ではサービスが提供する真正性確認手段があるかを別途確認し、利用可能なら送信元等と照合する。短期ログ等の設計とプライバシー配慮は必要。現存のcrメタデータにはUA/IPがなく、過去分をこの資料だけで確証に変えることはできない。

### 3c. crawlerOfの順序・includes — ⚠️ 要注意

一覧の各正式名だけなら、Claude-UserとClaudeBot、ChatGPT-UserとGPTBot、Perplexity-UserとPerplexityBotは相互の部分文字列ではない。通常の単一トークンが順序だけで別名になる直接の衝突は見つからない（index.js:549–568）。

ただし複数トークンを含むUAは先勝ち。たとえば `GPTBot ChatGPT-User` はGPTBot、`ClaudeBot Claude-User` はClaudeBotとなり、依頼読みから外れる。`FakeClaude-UserExtra` もClaude-Userに一致する。逆方向の偽装・別主体混入も可能。製品トークンの境界を定めて一致を取り、複数一致は曖昧として別集計し、真正性と分離する。UA判定だけでサービスや依頼主体を保証しない。

## 4. AIの依頼読みの横ばい

### 4a. 数える単位と傾向 — ⚠️ 要注意

週合計55→61→24は日別表の加算と一致する。日平均は7.86→8.71→6.00（最後は途中日込み4日割り）。ただし11/2〜5の同曜日は37件、11/9〜12は24件であり、『横ばいが確認できた』という強さには足りない。自己試行12件の除外有無でも評価が変わる。

**実装は1ページ1件ではなく1リクエスト1件。** 同じ / を2回取得すると2件。HEAD、再試行、リダイレクト元・先、404/500も非robotsなら入る（index.js:43,61,564、kpi.js:61–67）。`robots.txt` 以外の llms.txt 等は含む。資料の11/12の / 2件もその例。依頼数・利用者数・ユニークページ数には変換できない。

ChatGPT除外も `ok === '0'` だけで、`?`/欠落は含める（kpi.js:65）。『確かめられなかったものを全て除外』という `mcp.js:21` の説明と異なる。さらにCFの検証済みbot判定はChatGPTという主体の検証と同義ではない。検証方式・取得ページ数・UA構成・自己試行が変われば合計だけでも上下する。『この定義で観測された非robotsリクエスト数は55・61・今週途中24件。利用の横ばいは未確定』へ弱める。

### 4b. 永続日次集計・遅延・再送 — ❌ NG

`kpi.js:97–107` は同版の過去日JSONを返し続ける。`kpiCron:154–157` は前日ファイルがあれば終了し、5分ごとに更新するわけではない。日付直後の初回生成中に届いた前日分の保存等は後から反映されない。cron停止で空いた古い日はcron自体では埋めず、kpiRangeで作成上限つきの埋め戻し（123–134）となる。cronは保存済みの旧版・破損をheadで飛ばし、呼び出し時のgetKpiDayとは挙動も異なる。

より明確な誤りは日跨ぎの同じ v。evは**受信日**のprefixに保存（index.js:403–405）、KPIは日内だけで重複排除（kpi.js:70–75）。前日にn=0、翌日にn=1ならKPIでは1+1、期間全体のevStatsでは1件となる。実際のcomputeKpiDayを模擬R2で実行し再現した。翌日だけに初送信された表示は前日のページ閲覧でも翌日になる。これは『過去日の遅着で抜ける』とは別の日時帰属問題。

修正は安定した表示日・IDを定義して保存/集計を共通化し、閉じた日も一定猶予後に再集計、遅延更新を可能にすること。受信時刻と表示時刻は区別する。n最大での置換は加算ではないため、同日内で再計算するだけなら通常は二重計上しない。ただしこれらのバグが今回の20〜30→3を説明する規模かは未検証。

## 5. 計測の作り

### 5a. hは人が読んだ数か — ⚠️ 要注意

hは『bot条件に該当せず、列挙された操作の申告があった表示』である。人の読了や人数を表さない。静かに読む人・設定で記録しない人・送信できなかった人には過小になる一方、pointermoveだけで即離脱した人もhとなり、自動操作・合成イベント・u=1の偽装POSTでも増やせる（isTrusted等は未確認。index.js:372、SiteMeasure.astro:84–85）。人としての読書に対する総合的な偏り方向・大きさは判断できない。

名前を『操作あり表示』とし、xも別に示すのが妥当。見えた時間や深度を添えても読書の証明にはならない。フォーム・AIリンク等の指標も同じ選別バイアスを受ける。

### 5b. 再送の重ね方は両方同じか — ❌ NG

同一の読み込まれた集合では、双方とも v ごと n 最大、同値なら後から列挙された記録を採用する点は同じ（kpi.js:70–75、index.js:421–435）。ただしKPIは日ごと、evStatsはsince以降の全期間で同じvをまとめ、最大nを持つ記録の受信日に帰属させる。したがって前日件数が再送で別日へ移ることもある。両者は期間合計・日付帰属が一致しない（4bの再現）。evStatsには4万件の上限もある。

nはWorkerで50に丸める（index.js:391）。51回以降はnの大小が順序保証にならず、同値の後勝ちに依存する。安定した日付・重複排除範囲と同値時の時刻による採用規則を共通化し、上限の意味も定義する。BFCache復帰はfreshで別vにする設計（SiteMeasure.astro:221–223）なので、『タブに戻る再送』と『戻るボタンによる別表示』も分けて説明する。

### 5c. crStats打ち切りとhits — ❌ NG（打ち切り時の「最新200件」）

時刻はキーのepoch msから取り出してJST化し、降順ソートするため、**全件を読み切れた範囲では**最新200件の処理に明白な誤りはない（index.js:596,649以降）。同秒内の表示は秒単位に丸められ、別リクエストが同時刻に見える。robotsも含む。

問題は `index.js:590–599` で全botのcrを先に最大40ページ読んでから `625` でbot絞り込み、`649` でソートすること。キー順の古い側で打ち切られれば新しい記録を読んでいないため、返すのは**読めた範囲内の最新200件**であり、対象期間の最新200件ではない。bot指定でも他botが予算を使い切る。truncated=trueは出るが、hits独自の200件省略件数・継続カーソルはなく、truncated=falseでもそのbotが201件あれば全訪問履歴ではない。byBot/byWeek/errorsはbot指定でも全botを集計するので混同しない。

修正は日付prefixを新しい日から走査するかbot別の索引を設け、継続ページを返すこと。hitsの完全性・省略件数と集計対象を明示する。今回のhits取得でtruncated=falseだったかが資料にないため、『他に訪問がなかった』の根拠にはまだ使えない。sinceにuntilがなく、スナップショット時刻以降も再取得値は変わる点にも注意。

### 5d. 優先度評価 — ⚠️ 要注意

1. **最優先の未確定事項：実ユーザーだけの未送信・誤分類。** 原因の証拠はまだないが、結論1を支える検証がbの成功しか確認していない。実機でGET→JS→POST→h保存を確認し、拒否/分類の理由別件数とCF変更履歴を見る。
2. **確定した整合性不良：日跨ぎ再送、日次キャッシュ固定、範囲差。** 4b/5bの修正が必要。今回の原因と断定しない。
3. **分析に直結する表示・説明問題：0%の丸め、latest hitsの範囲、未確認ChatGPTの扱い、WebFetchの断定。** 生の分子/分母・完全性を返し、mcpの説明を修正する。
4. **送信の耐障害性と除外設定の例外処理。** SiteMeasure.astro:29–34 はlocalStorageが例外になるとq=1でもoffがfalseのままになりうる。『毎回の判定』というコメントどおりに除外できない。q=1を永続化の成否と独立に適用する。これは自身の閲覧混入による過大側の別バグで、今回の急減の証拠ではない。送信失敗の回収・稼働中のチェックポイントも設計する。
5. **指標の意味：AIは取得試行、hは操作あり表示。** 成功レスポンス/HEAD/重複/自己試行/未検証を分けないと利用人数や利用増減へ誤変換される。

## 最終サマリ

### 結論1〜4の扱い

| 結論 | 判定と採用すべき言い方 |
|---|---|
| 1：故障ではなく本当の減少 | **故障を否定した部分は撤回。** 『記録された操作あり表示は11/11に3件、11/12途中に2件。実減か選択的欠損かは未確定』 |
| 2：直接・不明とGoogleが減った | **記録上の11/11以降の減少に限定すれば可。** 週全体のGoogle大幅減や直接流入の実減とする言い方は弱める。異なる長さ・曜日・途中日の合計比較は避ける |
| 3：残り7回10ページは外部の人 | **外部帰属の断定を撤回。** 『自己試行と確認された11/3分を除き、7つの時刻群・非robots10取得は帰属未確認』。7依頼/7人とも確定しない |
| 4：AI依頼読みは横ばい | **55→61→途中24の観測値はそのまま可、横ばいは弱める。** 同期間・自己試行・取得単位・真正性を揃えるまでは傾向未確定 |

### 急減を決着させる次の確認（優先順、3つ）

1. **日本の実回線・実機で1件を端から端まで追う。** Safariと代表的アプリ内ブラウザで操作し、計測JS取得・例外・送信ヘッダー・応答・同じvのR2保存・k=h・幅・集計を対応させる。bで成功した確認だけでは終えない。
2. **11/10前後の本番設定/配信/拒否の変化を照合する。** CFのWAF・Bot・challenge・route・デプロイ/アセット/ヘッダー変更と、ページGET・JS取得・ev POSTの403/429/5xx・分類理由を時刻/端末等で確認。既存ログで足りなければ短期診断を設計する。一般ユーザーGETは現crに残らないのでcrだけでは代用できない。
3. **原記録を日付・範囲を固定して再集計し、独立指標と比較する。** 11/2〜12のev/cr原件数、h/b/x、sp実数、最大n、日跨ぎv、truncated、KPI madeAt/版を確認。同曜日・同締め時刻の比較と、確定後のSearch Consoleクリック/利用可能な配信ログを照合する。これでも『人数』の直接観測にはならない。

### コードで直すべきもの（優先順）

1. 日付帰属・重複排除をKPI/evStatsで共通化し、遅延分を取り込む再集計を設ける（kpi.js:70–107,154–157、index.js:403–405,421–435）。
2. 送信失敗を成功扱いする状態更新とfallbackを見直し、終了時だけに依存する欠損を減らす（SiteMeasure.astro:203–220）。同じv/nでの回収を設計し、単純な再送加算にしない。
3. hitsの最新性/完全性を保証または明示し、全bot先行打ち切りを解消する（index.js:590–599,625,649以降）。割合には分子/分母も返す（475–480）。
4. ChatGPTの未確認値の採否を定義と一致させ、成功取得と試行を区分する（kpi.js:63–66）。UAの境界・複数一致、CF検証と主体名の関係も明示する。
5. notrackのlocalStorage例外時の漏れを直し（SiteMeasure.astro:29–34）、WebFetch断定・『数え漏れがない』を修正する（mcp.js:21,28,48）。

本報告は原因確定の報告ではない。確定した実装上の不整合と、現資料で否定できない故障経路を区別した。コード・データへの修正は実施していない。
````


### 日ごとの数を取ったスクリプト（fetch_ev_by_day.py）

鍵は KIOXIA の p2m_stats_key.txt から読み、中身は表示しません。Worker の処理が重く、1回の実行で全部の日を取ると時間切れになったので、日付を4〜5日ずつ渡して3回に分けて動かしました。1回は Worker の資源の上限（Error 1102）で失敗し、その日は取り直しています。

```python
import json,subprocess,os,sys
K=open(os.path.expanduser('~/mnt/KIOXIA/p2m_stats_key.txt')).read().strip()
P=os.path.expanduser('~/days.json')
res=json.load(open(P)) if os.path.exists(P) else {}
def get(since,who):
    o=subprocess.run(['curl','-s','--max-time','60','-H','Authorization: Bearer '+K,f'https://pixelstomotors.com/api/ev-stats?format=json&since={since}&who={who}'],capture_output=True,text=True).stdout
    d=json.loads(o); w=d['byWeek']
    return dict(views=sum(x['views'] for x in w),sp=sum(round(x['spPct']*x['views']/100) for x in w),ref={r['from']:r['count'] for r in d['referrers']},trunc=d['truncated'])
for d in sys.argv[1:]:
    if d in res: continue
    res[d]={w:get(d,w) for w in ('human','bot','unknown')}
    json.dump(res,open(P,'w'),ensure_ascii=False)
print(sorted(res))
```


### 集計のスクリプト（summarize_LOG494.py）

```python
"""LOG494 の集計：ev-stats を「その日以降」で日ごとに取った値の差から、1日ずつの数を出す。

使い方: python3 summarize_LOG494.py <LOG494_data のフォルダ>
入力:  ev_by_since_day.json（fetch_ev_by_day.py が /api/ev-stats?since=日付&who=human|bot|unknown を取ったもの）
       kpi_since1026.json（/api/kpi-stats?since=2026-10-26）
       linkedin_posted_by_day.txt（r2r2r-content の git log から数えた LinkedIn の自動投稿の数）
出力:  標準出力（summarize_LOG494_output.txt に保存する）

注意：
- 差で出しているので、0時をまたいで送り直された表示は、送り直した日の側に寄る（ev-stats は期間の中で同じ表示を1件にまとめるため）
- スマホ幅（sp）は ev-stats が割合（四捨五入）で返すので、表示数×割合から戻した概数。1日ずつの差は当てにならないので、この表では使わない
"""
import json
import os
import sys

d = sys.argv[1]
r = json.load(open(os.path.join(d, 'ev_by_since_day.json')))
days = sorted(r)
zero = {'views': 0, 'sp': 0, 'ref': {}, 'trunc': False}

rows = []
for i, day in enumerate(days):
    nx = days[i + 1] if i + 1 < len(days) else None
    def diff(who, key):
        return r[day][who][key] - (r[nx][who] if nx else zero)[key]
    h, hn = r[day]['human'], (r[nx]['human'] if nx else zero)
    ref = {k: v - hn['ref'].get(k, 0) for k, v in h['ref'].items()}
    g = ref.get('www.google.com', 0)
    di = ref.get('（直接・不明）', 0)
    inner = ref.get('（サイト内）', 0)
    human = diff('human', 'views')
    rows.append({
        'day': day, 'human': human, 'bot': diff('bot', 'views'), 'unknown': diff('unknown', 'views'),
        'google': g, 'direct': di, 'inner': inner, 'other': human - g - di - inner,
        'truncated': any(r[day][w]['trunc'] for w in r[day]),
    })

print('== 1日ずつの表示（ev。人＝人の操作あり・機械・不明＝操作なし）と、人の表示の来た所')
print('日          人  機械 不明  Google 直接・不明 サイト内 その他  打ち切り')
for x in rows:
    print(f"{x['day']}  {x['human']:>3} {x['bot']:>5} {x['unknown']:>4}  {x['google']:>6} {x['direct']:>9} {x['inner']:>8} {x['other']:>6}  {x['truncated']}")

def total(ds, key):
    return sum(x[key] for x in rows if x['day'] in ds)

pairs = [
    ('月〜水', ['2026-11-02', '2026-11-03', '2026-11-04'], ['2026-11-09', '2026-11-10', '2026-11-11']),
    ('月〜火', ['2026-11-02', '2026-11-03'], ['2026-11-09', '2026-11-10']),
    ('水だけ', ['2026-11-04'], ['2026-11-11']),
]
print()
print('== 同じ曜日どうしの比べ（11/2の週 → 11/9の週）')
for name, a, b in pairs:
    print(f"{name}: 人 {total(a,'human')} → {total(b,'human')}　Google {total(a,'google')} → {total(b,'google')}　直接・不明 {total(a,'direct')} → {total(b,'direct')}　機械 {total(a,'bot')} → {total(b,'bot')}　不明 {total(a,'unknown')} → {total(b,'unknown')}")

k = json.load(open(os.path.join(d, 'kpi_since1026.json')))
print()
print('== AI の依頼読み（kpi。取得の回数・robots.txt を除く）')
for x in k['byDay']:
    print(f"{x['day']}  {x['aiReads']:>3}  {json.dumps(x['aiReadsByBot'], ensure_ascii=False)}{'  (途中)' if x['partial'] else ''}")
same = lambda ds: sum(x['aiReads'] for x in k['byDay'] if x['day'] in ds)
print(f"11/2〜11/4: {same(['2026-11-02','2026-11-03','2026-11-04'])}　11/9〜11/11: {same(['2026-11-09','2026-11-10','2026-11-11'])}")
print(f"11/2〜11/4（11/3 の試し12件を除く）: {same(['2026-11-02','2026-11-03','2026-11-04']) - 12}")

lp = os.path.join(d, 'linkedin_posted_by_day.txt')
if os.path.exists(lp):
    print()
    print('== LinkedIn の自動投稿の数（日本時間・r2r2r-content の「の結果（posted）」の commit）')
    print(open(lp, encoding='utf-8').read().rstrip())
```


### 集計の出力（summarize_LOG494_output.txt）

```
== 1日ずつの表示（ev。人＝人の操作あり・機械・不明＝操作なし）と、人の表示の来た所
日          人  機械 不明  Google 直接・不明 サイト内 その他  打ち切り
2026-10-30   10   280   12       1         5        0      4  False
2026-10-31   18   255    4       3         6        9      0  False
2026-11-01   13   225    4       4         2        7      0  False
2026-11-02   30   250    6       5        20        2      3  False
2026-11-03   25   243   10       4        12        7      2  False
2026-11-04   16   349    5       8         7        0      1  False
2026-11-05   21   340   10       4        12        3      2  False
2026-11-06   29   309    4      12         7        4      6  False
2026-11-07   10   325   10       3         5        1      1  False
2026-11-08    5   365    2       1         4        0      0  False
2026-11-09   28   383    9       8         4       12      4  False
2026-11-10   20   319    6       9         9        2      0  False
2026-11-11    3   374    1       1         1        0      1  False
2026-11-12    2   313    2       1         1        0      0  False

== 同じ曜日どうしの比べ（11/2の週 → 11/9の週）
月〜水: 人 71 → 51　Google 17 → 18　直接・不明 39 → 14　機械 842 → 1076　不明 21 → 16
月〜火: 人 55 → 48　Google 9 → 17　直接・不明 32 → 13　機械 493 → 702　不明 16 → 15
水だけ: 人 16 → 3　Google 8 → 1　直接・不明 7 → 1　機械 349 → 374　不明 5 → 1

== AI の依頼読み（kpi。取得の回数・robots.txt を除く）
2026-10-26    9  {"ChatGPT-User": 8, "Claude-User": 1}
2026-10-27   13  {"ChatGPT-User": 13}
2026-10-28    4  {"ChatGPT-User": 4}
2026-10-29    4  {"ChatGPT-User": 4}
2026-10-30   17  {"Claude-User": 1, "ChatGPT-User": 16}
2026-10-31    6  {"ChatGPT-User": 5, "Claude-User": 1}
2026-11-01    2  {"ChatGPT-User": 2}
2026-11-02    7  {"ChatGPT-User": 7}
2026-11-03   22  {"Claude-User": 12, "ChatGPT-User": 10}
2026-11-04    5  {"ChatGPT-User": 5}
2026-11-05    3  {"ChatGPT-User": 3}
2026-11-06    5  {"ChatGPT-User": 5}
2026-11-07   13  {"ChatGPT-User": 9, "Claude-User": 4}
2026-11-08    6  {"ChatGPT-User": 6}
2026-11-09    2  {"ChatGPT-User": 2}
2026-11-10    6  {"ChatGPT-User": 5, "Claude-User": 1}
2026-11-11   13  {"ChatGPT-User": 10, "Claude-User": 3}
2026-11-12    3  {"ChatGPT-User": 1, "Claude-User": 2}  (途中)
11/2〜11/4: 34　11/9〜11/11: 21
11/2〜11/4（11/3 の試し12件を除く）: 22

== LinkedIn の自動投稿の数（日本時間・r2r2r-content の「の結果（posted）」の commit）
2026-11-04 4
2026-11-05 4
2026-11-06 4
2026-11-07 3
2026-11-08 2
2026-11-09 2
2026-11-10 1
2026-11-11 1
2026-11-12 1

-- 1本ずつ（日本時間 投稿名）
2026-11-04 07:30 MANGA_ep131-linkedin 
2026-11-04 08:00 ISSUE-embodied-ai-security-linkedin 
2026-11-04 17:00 LOG389-linkedin 
2026-11-04 19:35 VIDEO_ai-yesterday-linkedin 
2026-11-05 07:30 MANGA_ep130-linkedin 
2026-11-05 08:00 ISSUE-tacit-knowledge-capture-linkedin 
2026-11-05 17:00 LOG391-linkedin 
2026-11-05 19:30 VIDEO_softbank-pudu-no1-linkedin 
2026-11-06 07:30 MANGA_ep129-linkedin 
2026-11-06 08:00 ISSUE-foundation-model-concentration-linkedin 
2026-11-06 17:00 LOG392-linkedin 
2026-11-06 19:15 VIDEO_votoms-at-linkedin 
2026-11-07 07:30 MANGA_ep128-linkedin 
2026-11-07 08:00 ISSUE-price-structure-smb-linkedin 
2026-11-07 18:00 VIDEO_kddi-elyza-robotics-linkedin 
2026-11-08 07:30 MANGA_ep127-linkedin 
2026-11-08 08:00 ISSUE-sier-engineering-bottleneck-linkedin 
2026-11-09 07:30 MANGA_ep126-linkedin 
2026-11-09 08:00 ISSUE-liability-demarcation-linkedin 
2026-11-10 17:00 LOG393-linkedin 
2026-11-11 17:00 VIDEO_ghost-remote-body-linkedin 
2026-11-12 17:00 ISSUE-failsafe-stop-design-linkedin
```


### Search Console から写した数（search_console_20261112.txt）

```
Google Search Console（sc-domain:pixelstomotors.com・検索タイプ：ウェブ）を 2026-11-12 19:10 ごろ（日本時間）に Chrome で開いて写した値。
画面の「最終更新日」は 6 時間前。新しい日の数は2〜3日遅れて確定するので、11/10 以降は途中の数の可能性がある。

■ 7日間（1日ごと）
日付        クリック  表示回数
2026/11/04      2        96
2026/11/05      6       133
2026/11/06      5        98
2026/11/07      1        70
2026/11/08      4        95
2026/11/09      6       148
2026/11/10      2        21
合計           26       661（平均 CTR 3.9%・平均掲載順位 15.8）

■ 24時間（1時間ごと・2026/11/11 13:00 から）
合計クリック 0・合計表示回数 3・平均掲載順位 33.7

■ 自前の計測（ev・人の操作ありの表示）で Google から来た数（比べるため）
11/04 8・11/05 4・11/06 12・11/07 3・11/08 1・11/09 8・11/10 9・11/11 1・11/12 1（19時ごろまで）
```


### Claude-User の1回ずつの訪問（cr-stats・bot=Claude-User・11/9 から）

11/3 からで取ると、記録の読み込みが打ち切られた印（truncated）が付きました。11/9 からで取ると打ち切りはなく、11/9 以降の部分は両方で同じ9件でした。下は11/9 からの hits です。

```json
[
 {
  "at": "2026-11-12 13:18:00",
  "path": "/",
  "via": "",
  "status": "200",
  "verified": "0"
 },
 {
  "at": "2026-11-12 13:18:00",
  "path": "/robots.txt",
  "via": "",
  "status": "200",
  "verified": "0"
 },
 {
  "at": "2026-11-12 13:17:59",
  "path": "/",
  "via": "",
  "status": "200",
  "verified": "0"
 },
 {
  "at": "2026-11-11 14:05:22",
  "path": "/message",
  "via": "",
  "status": "200",
  "verified": "0"
 },
 {
  "at": "2026-11-11 13:46:10",
  "path": "/",
  "via": "",
  "status": "200",
  "verified": "0"
 },
 {
  "at": "2026-11-11 13:46:10",
  "path": "/robots.txt",
  "via": "",
  "status": "200",
  "verified": "0"
 },
 {
  "at": "2026-11-11 13:46:10",
  "path": "/",
  "via": "",
  "status": "200",
  "verified": "0"
 },
 {
  "at": "2026-11-10 21:08:38",
  "path": "/record/making-explainer-video-with-ai",
  "via": "",
  "status": "200",
  "verified": "0"
 },
 {
  "at": "2026-11-10 21:08:37",
  "path": "/robots.txt",
  "via": "",
  "status": "200",
  "verified": "0"
 }
]
```


### 計測のコードに入れた変更（11/12 の4つの commit）

```diff
commit 71cb145（2026-11-12 16:15）
crawler_visits：bot を指定したとき、1回ずつの訪問（日本時間の時刻・ページ）を hits に返す（Claude-User の読みがエイイチ・Claude の試しかを時刻で突き合わせるため）

diff --git a/worker/index.js b/worker/index.js
index bbe919f..e327cdb 100644
--- a/worker/index.js
+++ b/worker/index.js
@@ -593,7 +593,7 @@ async function crStats(request, env, url) {
       if (!m.b) continue;
       const day = o.key.split('/')[1];
       if (since && day < since) continue;
-      rows.push({ ...m, day, week: evWeekOf(day) });
+      rows.push({ ...m, day, week: evWeekOf(day), at: Number(o.key.split('/')[2].split('-')[0]) || 0 });
     }
     cursor = r.truncated ? r.cursor : undefined;
     if (++pages >= 40 && cursor) { truncated = true; break; }
@@ -644,6 +644,11 @@ async function crStats(request, env, url) {
     byVia: [...viaMap.values()].sort((a, b) => b.visits - a.visits).map((e) => ({ via: e.via, visits: e.visits, records: e.records.size, bots: [...e.bots].sort((a, b) => b[1] - a[1]).map(([b, n]) => `${b} ${n}`).join('、'), last: e.last })),
     byViaWeek: [...viaWeeks].sort((a, b) => b[0].localeCompare(a[0])).map(([week, m]) => ({ week, total: [...m.values()].reduce((x, y) => x + y, 0), via: [...m].sort((a, b) => b[1] - a[1]).map(([v, n]) => `${v} ${n}`).join('、') })),
     errors: [...errMap.values()].sort((a, b) => b.visits - a.visits).slice(0, 100).map((e) => ({ path: e.path, status: e.status, visits: e.visits, bots: [...e.bots].join('、'), last: e.last })),
+    // ?bot= のときは1回ずつの訪問（日本時間の時刻・ページ・「AIで読む」の印・結果）を新しい順に200件まで。
+    // エイイチや Claude の作業の時刻と突き合わせて、試しの分かどうかを見分けるため（2026-11-12）
+    ...(only ? { hits: scope.filter((r) => r.at).sort((a, b) => b.at - a.at).slice(0, 200).map((r) => ({
+      at: new Date(r.at + 9 * 3600e3).toISOString().slice(0, 19).replace('T', ' '), path: r.p, via: r.v || '', status: r.s, verified: r.ok,
+    })) } : {}),
   };
   if (url.searchParams.get('format') === 'json') {
     return new Response(JSON.stringify(data), { headers: { 'content-type': 'application/json; charset=utf-8', 'x-robots-tag': 'noindex', 'cache-control': 'no-store' } });
diff --git a/worker/mcp.js b/worker/mcp.js
index c20a9c3..b19e7d1 100644
--- a/worker/mcp.js
+++ b/worker/mcp.js
@@ -70,7 +70,7 @@ const TOOLS = [
     description: 'どのクローラーが・どのページを読んだか（/api/cr-stats）。返せなかったページ（400以上）も。長い期間を指定すると一部しか数えない（truncated）ので、since は2週間以内にする。',
     inputSchema: { type: 'object', properties: {
       since: { type: 'string', description: 'この日以降（YYYY-MM-DD）。省略すると7日前' },
-      bot: { type: 'string', description: 'ページごとの表をこのクローラーだけに（例 ChatGPT-User）' },
+      bot: { type: 'string', description: 'ページごとの表をこのクローラーだけに（例 ChatGPT-User）。指定すると1回ずつの訪問（日本時間の時刻・ページ）も hits に返す' },
     } },
     annotations: { readOnlyHint: true, openWorldHint: false },
   },
commit b1a185a（2026-11-12 16:18）
how_to_read：AI の依頼読みが試しの分かは、hits の時刻とチャットの履歴を突き合わせて確かめる（11/3 の Claude-User 12件は LOG437 の試しと確認）

diff --git a/worker/mcp.js b/worker/mcp.js
index b19e7d1..540b70d 100644
--- a/worker/mcp.js
+++ b/worker/mcp.js
@@ -24,7 +24,7 @@ const GUIDE = `# Pixels to Motors（pixelstomotors.com）のサイトの計測
 
 ## 混ざりうるもの（数を読む前に必ず思い出す）
 - aiReads の viaButton は記事の「AIで読む」ボタン経由。エイイチや Claude の試しが混ざりうる。ボタンの利用そのものは site_usage の押したもの（btn:AIで読む・場所 ai）で人のクリックを見る。crawler_visits の byVia は Amazonbot などのクローラーがボタンの行き先をたどった分が大半で、利用の数としては使えない（2026-11-05 に判明）
-- aiReads には、エイイチ自身が ChatGPT・Claude にこのサイトのことを聞いた分も入りうる（見分けられない）。トップ（/）が多い日はそれを疑う
+- aiReads には、エイイチ自身が ChatGPT・Claude にこのサイトのことを聞いた分も入りうる。名乗りだけでは見分けられないので、crawler_visits に bot（例 Claude-User）を指定して hits の時刻を出し、エイイチ・Claude の作業の時刻（チャットの履歴）と突き合わせて確かめる。「混ざりうる」で済ませない（2026-11-12）。例：11/3 09:26〜09:29 の Claude-User 12件は、LOG437 で TOP の「AIで読む」を Claude で試した分だった
 - Claude のセッションが WebFetch でサイトを読むと Claude-User として入りうる
 - 人の数は 2026-10-26 から（それより前は人と機械を分けていない）。人の表示の約9割は機械なので、来訪の数は必ず人だけ（who=human）で見る
 - エイイチ・Claude の確認の閲覧は ?p2m-notrack=1 を付けたブラウザでは送られない。付け忘れた自動のブラウザは navigator.webdriver で機械に入る
commit 1e04e85（2026-11-12 16:34）
how_to_read：Claude の作業のセッションの WebFetch は Claude-User に入っていないことを記す

diff --git a/worker/mcp.js b/worker/mcp.js
index 540b70d..de00bcf 100644
--- a/worker/mcp.js
+++ b/worker/mcp.js
@@ -25,7 +25,7 @@ const GUIDE = `# Pixels to Motors（pixelstomotors.com）のサイトの計測
 ## 混ざりうるもの（数を読む前に必ず思い出す）
 - aiReads の viaButton は記事の「AIで読む」ボタン経由。エイイチや Claude の試しが混ざりうる。ボタンの利用そのものは site_usage の押したもの（btn:AIで読む・場所 ai）で人のクリックを見る。crawler_visits の byVia は Amazonbot などのクローラーがボタンの行き先をたどった分が大半で、利用の数としては使えない（2026-11-05 に判明）
 - aiReads には、エイイチ自身が ChatGPT・Claude にこのサイトのことを聞いた分も入りうる。名乗りだけでは見分けられないので、crawler_visits に bot（例 Claude-User）を指定して hits の時刻を出し、エイイチ・Claude の作業の時刻（チャットの履歴）と突き合わせて確かめる。「混ざりうる」で済ませない（2026-11-12）。例：11/3 09:26〜09:29 の Claude-User 12件は、LOG437 で TOP の「AIで読む」を Claude で試した分だった
-- Claude のセッションが WebFetch でサイトを読むと Claude-User として入りうる
+- Claude の作業のセッション（Claude Code の WebFetch）がサイトを読んでも、Claude-User には入っていない（11/8 に LOG476 のチャットが /serving-robot-one-less-staff を WebFetch したが、その日の Claude-User は0件。2026-11-12 に確認）。Claude-User に入るのは claude.ai のチャットでの読み（「AIで読む」ボタンを含む）
 - 人の数は 2026-10-26 から（それより前は人と機械を分けていない）。人の表示の約9割は機械なので、来訪の数は必ず人だけ（who=human）で見る
 - エイイチ・Claude の確認の閲覧は ?p2m-notrack=1 を付けたブラウザでは送られない。付け忘れた自動のブラウザは navigator.webdriver で機械に入る
 - crawler_visits（/api/cr-stats）は長い期間を指定すると記録が多すぎて一部しか数えない（truncated が true）。2026-10-25 からの合計は少なめに出ていた。日ごとの数は kpi（日ごとに集計して残したもの）で見る
commit 8af4e01（2026-11-12 18:58）
計測：?p2m-notrack=1 を覚えられないブラウザでも、その表示は送らない／読み方の説明を Codex の検証（11/12）に合わせて直す（依頼読みは取得の回数・WebFetch は未確認・日ごとの集計の抜けと二重）

diff --git a/src/components/SiteMeasure.astro b/src/components/SiteMeasure.astro
index 1bea227..59ebf8b 100644
--- a/src/components/SiteMeasure.astro
+++ b/src/components/SiteMeasure.astro
@@ -32,6 +32,8 @@
     if (q === '0') localStorage.removeItem(OPT);
     off = localStorage.getItem(OPT) === '1';
   } catch { saved = false; /* 覚えられない環境では、送るかどうかを毎回の判定だけで決める */ }
+  // 覚えられない環境でも、?p2m-notrack=1 で開いたその表示は送らない（2026-11-12 Codex の指摘：例外のとき除外が効かなかった）
+  if (q === '1') off = true;
   const nav = navigator as Navigator & { globalPrivacyControl?: boolean };
   const dnt = nav.doNotTrack === '1' || nav.globalPrivacyControl === true;
   if (dnt) off = true;
diff --git a/worker/mcp.js b/worker/mcp.js
index de00bcf..49ca4d1 100644
--- a/worker/mcp.js
+++ b/worker/mcp.js
@@ -18,14 +18,14 @@ const GUIDE = `# Pixels to Motors（pixelstomotors.com）のサイトの計測
 
 ## いま主に見る3つの数字（2026-11-06 にエイイチが決めた）
 サイトのねらい：AI に調べられることで、人の来訪や知名度がいつ増えはじめるかを見る。サイトはもともと検索で人を集める作りにしていない。
-1. AI の利用者の依頼で読みに来た数（aiReads）：ChatGPT-User・Claude-User・Perplexity-User・MistralAI-User が読んだページの数。/robots.txt は数えない。ChatGPT-User のうち Cloudflare が本物と確かめられなかったものは入れず、unverifiedChatGPTExcluded に別に数える。Claude-User は Cloudflare が確かめないので全部入れる
+1. AI の利用者の依頼で読みに来た数（aiReads）：ChatGPT-User・Claude-User・Perplexity-User・MistralAI-User のページの取得の回数（ページの数・依頼の数・人数ではない。同じページを2回取れば2件、/llms.txt も入る）。/robots.txt は数えない。ChatGPT-User のうち Cloudflare が本物でないとしたもの（ok=0）は入れず unverifiedChatGPTExcluded に別に数える（判定がないもの ? は入る）。Claude-User は Cloudflare が確かめないので全部入る。名乗りは偽れるので、本物かどうかは確かめていない
 2. AI のサービスのリンクから来た人の数（aiReferrals）：referrer が chatgpt.com などか、リンクの印 utm_source が chatgpt.com などの表示のうち、人の操作（マウス・指・キー）があったものだけ。機械・操作なしは notHumanExcluded に別に数える
 3. サイト名で検索して来た人の数（nameSearch）：Search Console のサイト名（Pixels to Motors・pixelstomotors など）の検索のクリック数。今は週の分析のときに Claude が Search Console（Chrome 拡張・新旧ドメインの両方）を見て、record_name_search で週ごとに書き足す（2026-11-06 決定。API の自動取得は Google Workspace の組織のポリシーでサービスアカウントの鍵が作れず保留。鍵 GSC_SA_KEY を入れれば毎日自動に切り替わる）。数は2〜3日遅れて確定し、人数の少ない検索語は Search Console が伏せるので少なめに出る。kpi の nameSearch に週ごとの記録（byDay・検索語・検索全体のクリック allClicks）が出る
 
 ## 混ざりうるもの（数を読む前に必ず思い出す）
 - aiReads の viaButton は記事の「AIで読む」ボタン経由。エイイチや Claude の試しが混ざりうる。ボタンの利用そのものは site_usage の押したもの（btn:AIで読む・場所 ai）で人のクリックを見る。crawler_visits の byVia は Amazonbot などのクローラーがボタンの行き先をたどった分が大半で、利用の数としては使えない（2026-11-05 に判明）
 - aiReads には、エイイチ自身が ChatGPT・Claude にこのサイトのことを聞いた分も入りうる。名乗りだけでは見分けられないので、crawler_visits に bot（例 Claude-User）を指定して hits の時刻を出し、エイイチ・Claude の作業の時刻（チャットの履歴）と突き合わせて確かめる。「混ざりうる」で済ませない（2026-11-12）。例：11/3 09:26〜09:29 の Claude-User 12件は、LOG437 で TOP の「AIで読む」を Claude で試した分だった
-- Claude の作業のセッション（Claude Code の WebFetch）がサイトを読んでも、Claude-User には入っていない（11/8 に LOG476 のチャットが /serving-robot-one-less-staff を WebFetch したが、その日の Claude-User は0件。2026-11-12 に確認）。Claude-User に入るのは claude.ai のチャットでの読み（「AIで読む」ボタンを含む）
+- Claude の作業のセッション（Claude Code の WebFetch）の読みが Claude-User に入るかは確かめていない（11/8 の1回は対応する記録が見つからなかったが、それだけで入らないとは言えない。2026-11-12 Codex の指摘）。だれの読みかは、時刻とチャットの履歴が合ったものだけを「試し」と言い、合わないものは「未確認」と書く（外の人とも言わない）
 - 人の数は 2026-10-26 から（それより前は人と機械を分けていない）。人の表示の約9割は機械なので、来訪の数は必ず人だけ（who=human）で見る
 - エイイチ・Claude の確認の閲覧は ?p2m-notrack=1 を付けたブラウザでは送られない。付け忘れた自動のブラウザは navigator.webdriver で機械に入る
 - crawler_visits（/api/cr-stats）は長い期間を指定すると記録が多すぎて一部しか数えない（truncated が true）。2026-10-25 からの合計は少なめに出ていた。日ごとの数は kpi（日ごとに集計して残したもの）で見る
@@ -45,7 +45,7 @@ const TOOLS = [
   {
     name: 'kpi',
     title: '3つの数字（日ごと・週ごと）',
-    description: 'いま主に見る3つの数字を返す：AI の利用者の依頼で読みに来た数・AI のサービスのリンクから来た人の数・サイト名で検索して来た人の数（Search Console から記録した分）。日ごとに集計して残したものなので速く、数え漏れがない。混ざりうるものは how_to_read を読むこと。日付は日本時間、週は月曜はじまり。',
+    description: 'いま主に見る3つの数字を返す：AI の利用者の依頼で読みに来た数・AI のサービスのリンクから来た人の数・サイト名で検索して来た人の数（Search Console から記録した分）。日ごとに集計して残したものなので速い。ただし作ったあとに届いた記録は入らず、0時をまたいで送り直された表示は2日に1件ずつ数えることがある（2026-11-12 Codex の指摘・未修正）。混ざりうるものは how_to_read を読むこと。日付は日本時間、週は月曜はじまり。',
     inputSchema: { type: 'object', properties: {
       since: { type: 'string', description: '始めの日（YYYY-MM-DD）。省略すると28日前。2026-10-26 より前は数えない' },
       until: { type: 'string', description: '終わりの日（YYYY-MM-DD）。省略すると今日（今日は途中の数）' },
```


## 次は、11/15 以降に Search Console の確定値と、実機の1件の記録を見る

Search Console の11/10〜11/12 の数が確定したら、表示回数が本当に落ちたかを見ます。落ちていれば Google の側の変化として原因を探し、落ちていなければ人の記録の道筋を疑います。それと並べて、アプリの中のブラウザから印を付けた住所を1件開き、記録が人として残るかを追います。0時をまたぐ二重の数え方は、日付の決め方をそろえてから直します。
