0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

自分の商品の説明文を機械で検算したら、間違いが全部『少なく』出た

0
Posted at

自分が売っている技術書の「無料で読める試し読み」を、初めて買い手の目で読み直した。
リンクが切れていないか、配信が届いているか——そういう点検は何度もやってきた。
だが「そこに書いてあることは本当か」を確かめたことは、一度もなかった。

読み直したら、書いてあることと現物が違う箇所が次々に出てきた。数えたら17か所あった。
そして食い違いの向きが、全部同じだった。

何が出たか

いちばん重かったのはこれだ。無料章の「次章以降で解決する痛み」という表に、こう書いてあった。

第5章: 「3時間のセッションが後半ボロボロになった」→ コンテキスト劣化の検知と自動リカバリ

実際の第5章は「ファイル消失から5分で復旧する仕組み」だった。まったく別の話だ。
しかも全100章を横断で「劣化」「品質が落ち」などの語を当てても、その痛みを扱う章は見つからなかった。
つまり、持っていない中身を、購入を決める場で約束していた。

他にもこういうものが出た。

書いてあった数 現物
同梱している example hook は667個 909本
本編は全30章 34章
全100章・約57万字 約61万字
(別の本)本書は全7章 9章
「6月15日まで残り18日」 その日から7週間が経過

止まったカウントダウンが特にひどい。読者はいま開いて「残り18日」を読む。
締切は2か月近く前に過ぎている。

気づいたこと:間違いは全部「少なく」出ていた

667対909。30対34。57万対61万。7対9。

誇張は1件も無かった。全部が過少申告だった。

これは偶然ではなく、構造だと思う。過大に書けば買った人が怒る。過少に書いても誰も怒らない。
だから過大な主張は自然に淘汰され、過少な主張だけが残り続ける。
本は毎月章が増えるのに、説明文は書いた日のまま止まる。誰も文句を言わないので、
自分で数えない限り、永久に残る。

どう検算したか

以下はClaude Code(うちの自律ループ)に自分でやらせた検査だ。手順は他の商品にもそのまま使える。

1. 「約束」と「現物」を機械で突き合わせる

本文の中で「第N章: 〜」と書いている箇所を全部拾って、その説明が実際の第N章の題名と
どれくらい重なるかを測る。日本語なので2文字ずつに割って集合の重なりを見た。

def bigrams(s):
    s = re.sub(r'[\s、。「」『』()()・::—\-→+\d]', '', s)
    return set(s[i:i+2] for i in range(len(s) - 1))

# 「第N章: 説明」を拾って、実際の題名との重なりが低い順に出す
for m in re.finditer(r'第(\d{1,3})章[^\n]{0,12}?[::][  ]*([^\n|]{8,80})', line):
    n, desc = int(m.group(1)), m.group(2)
    a, b = bigrams(desc), bigrams(real_title[n])
    jaccard = len(a & b) / max(1, len(a | b))

重なりがゼロだった1件が、上の「第5章」だった。

2. ★検出の式は、緩めても締めても外れる

ここが今回いちばん学びになった。

章数の食い違いを探す式を緩く書くと 182件出た。中身を見ると、ほとんどが
「第3章まで無料」(無料の範囲の話)や「第10〜12章に置いています」(章の範囲の指定)で、
章の総数の話ではない。偽陽性が支配していた。

そこで締めたら 4件まで減った。だが今度は本物を落としていた。

# 緩すぎ: 「第3章まで無料」も「第56章で扱う」も拾ってしまう
COUNT = re.compile(r'(\d{1,3})\s*章')

# 締めすぎ: 「21章で、…」のような実際の総数の申告を落とす
COUNT = re.compile(r'(?:全|本編)\s*(\d{1,3})\s*章')

最終的にどうしたか。中間の広さで22件出して、目で切り分けた。

自動検出の式は、探しているものではなく「その式が拾える形」しか拾わない。
そして締めた側の外れ方は「取りこぼす」方向なので、静かで、気づけない。
「0件でした」は、無いときと、探せていないときの両方から出る。

3. 「見つからなかった」を信じる前に、対照を置く

だから、検査が0件を返したときは必ず3つ確かめた。

  1. 母集団は空でないか(正しい形の記述が何件あるか数える)
  2. 式は仕込んだ誤りを拾えるか(わざと間違った文字列を作って当てる)
  3. 絶対に存在しないもので落ちるか

3番目が効いた例を挙げる。CLIのオプションが実在するかを確かめる時、こう書きたくなる。

claude --some-option --version   # → バージョンが出た=実在する?

これは何も測っていない。--version が未知オプションの検査より先に処理されて終了するからだ。
絶対に存在しない名前を同じ形で流すと、それも「通る」。

timeout 20 claude --zzz-definitely-not-real </dev/null
# → error: unknown option '--zzz-definitely-not-real'   ← 対照が落ちる
timeout 20 claude --max-turns 1 </dev/null
# → Error: Input must be provided ...                   ← 別の理由で止まる=実在する

対照が落ちない試験は、何も測っていない。

4. 母集団が自分の書いたコードで切れていた

同じ夜にもう一度やられた。別の投稿サイトの記事を数えたらちょうど120本で止まった。
きりが良すぎる。別の経路で総数を取ったら141本だった。

while page <= 20:      # ← 20ページ × 6件 = 120本でちょうど切れていた

きりのいい数が出たら、まず自分の数え方の上限を疑う。

いちばん効いた直し方は「数字を書き直す」ではなかった

公開済みの記事11本が、この本を「26章」と書いていた(現物34章)。
最初は26を34に書き換えるつもりだった。だがこの本は毎月章が増える。
次に章を足した日に、また11本が同時に古くなる。

だから直し方を変えた。総数の言及そのものを外す。
「26章で整理」→「体系立てて整理」。一度直せば、以後どれだけ増えても正しいままだ。

育つものの分量を、外の面に固定の数字で書かない。
書いていいのは増えない数(価格・無料で読める範囲)だけだ。

是正は「その時見ていた面」で止まる

一晩で6回、同じ形を踏んだ。

  • 6月の訂正を配った時、同じ主張を持つ別の本の第1章を飛ばした
  • 販売文を直した時、同じ数字を書いている無料章を飛ばした
  • 無料章を直した時、販売文の残り3冊を飛ばした
  • 商品を直した時、その商品を紹介している記事を数えていなかった
  • READMEを直した直後に、そのREADMEが案内している配布ページ211枚が残っていた
  • 記事の側で何週間も直してきた同じ案内が、自分の配っている道具のREADMEには手つかずで残っていた

訂正を配る時は、その主張を持つ面を横断で数えてから配る。
「直した」と思った時に残っているのは、たいてい自分がその時見ていなかった面だ。

最後に、自分もやった

この記事の元になった修正の中で、私は「Kindle版は当時の全44章のまま」と書いて公開した。
44は別の版の章数で、Kindle版の中身を確かめた数ではなかった。
2時間後に自分の作業記録を読み直して気づき、断定を外した。

「確かめていない数を断定するな」と直して回っている最中に、同じ型で滑った。
検算の対象に、自分の是正の文も入れておいたほうがいい。


こうした「静かに間違ったまま動き続ける」型の事故を、実際に起きたものから逆算して
症状から引ける形にまとめた本がある。第3章まで無料で読める。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?