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?

自動化バグで参照パスが壊れた話: ID生成とregexの境界をそろえる

0
Posted at

自動化の失敗には、派手な例外で止まるものと、起動前に入力が壊れていて何も始まらないものがあります。

今回扱うのは後者です。カード側には、今回の題材が次のように記録されていました。

"id": "AUTO-W3-CT-QIITA-20260902-pm"
emitのslot注入が publish カードの参照パスを二重接尾辞に壊し、配信5本が起動前に死んでいた

この時点で見るべき対象は、投稿APIでも、Qiitaの本文でもありません。content から publish へ渡すカードIDと参照パスの整合です。

事象

配信レーンでは、Qiita は技術ストックとして扱われています。運用メモにも次のようにあります。

Qiita | @SciCos | 稼働 | 技術ストック・信頼蓄積→送客

同時に、投稿上限は次の設定です。

"qiita": { "per_day": 1 }

つまり、1日に1本の枠を使う publish カードが、参照先不整合で起動前に落ちると、その日の配信枠を丸ごと失います。

今回のカードにも、前段の publish が失敗する前提が明示されています。

既存のQIITA publishは参照先が存在せず必ず落ちるので撃ち直し

ポイントは「記事が悪い」のではなく、「記事へ到達するための参照パスが壊れていた」ことです。

再現条件

再現条件は、IDやファイル名を文字列として組み立てる処理で、同じ意味の接尾辞を2回付けられる状態にしてしまうことです。

今回の作業カードは、成果物を次のように指定しています。

"deliverable": "qiita-posts.md"

一方で、過去のQiita公開ログには、上流contentカードとpublishカードが別IDとして残っています。

"path":"_share/outputs/banto/2026-09-01/AUTO-C1-CT-QIITA-20260901-am/AUTO-C1-CT-QIITA-20260901-am-qiita-post.md"
"source":"AUTO-C1-PUB-QIITA-20260901-am"

この構造では、CT 側の成果物名と PUB 側の参照先が少しでもずれると、publish は本文を読む前に失敗します。

再現しやすいのは、次のような考え方を混ぜたときです。

slot = qiita
baseId = AUTO-W3-CT-QIITA-20260902-pm
deliverable = qiita-posts.md

baseId にすでに QIITA が入っているのに、slot注入側でも qiita 接尾辞を足す。さらに成果物名にも qiita が入っている。こうなると、人間には「Qiita用」と読めても、機械的な参照パスでは二重接尾辞になりやすいです。

原因のコード

許可された素材内に残っている実コード断片として、直近のQiita publish修正ログに parser の正規表現が記録されています。

正規表現: ^TITLE:s*\r?\n(.+?)\r?\n\r?\nTAGS:s*\r?\n(.+?)\r?\n\r?\nBODY:s*\r?\n([sS]*)$

このログは別件、つまり TITLE: / TAGS: / BODY: のラベル形式を読めず、タイトルやタグが壊れた事故の修正記録です。記録にはこうあります。

上流原稿のTITLE:/TAGS:/BODY:ラベル形式(コロン区切り・複数行値)に未対応
タイトルがファイル名(AUTO-C1-CT-QIITA-20260901-am-qiita-post)・タグが既定値(GAS,Gemini)・本文にTITLE:/TAGS:/BODY:ラベル行が生混入

ここから分かるのは、本文パーサとカード参照は別の場所で壊れていても、根は同じだということです。

文字列の境界を、正規表現の都合やファイル名の都合に寄せすぎると、構造化データだったものが「たまたま一致する文字列」になります。

今回の参照パス不整合でも、危ないのはこの形です。

既にslotを含むID + slot由来の接尾辞 + deliverable由来の接尾辞

ID生成、成果物名、publish側の参照先を別々の正規表現で処理すると、どこか1か所の「補正」が別の場所では「二重付与」になります。

修正

修正方針は、文字列を後から削ることではなく、境界を1か所に決めることです。

今回のカードは、最終成果物の形式を明示しています。

出力形式= TITLE= / TAGS= / BODY=

この場合、publish 側に渡すべきものは「Qiitaっぽいファイルを探す」ことではありません。カードの deliverable を正として、その1ファイルを読むことです。

"deliverable": "qiita-posts.md"

また、公開ログの修正例では、パーサ不一致を投稿後に緩和するのではなく、ツール側の分岐を追加してPATCHで訂正しています。

ツールにtitleColonMatch分岐を追加
既定回避せずツール修正=[[feedback_fix_tool_not_relax_rule]]

参照パスの問題でも同じです。publishカードごとに「存在しそうな別名」を探すのではなく、生成側と消費側で次を固定します。

content card id
deliverable path
publish source id
publish input path

この4つを1つの構造として渡せば、slot注入は表示や分類のための値になり、ファイル参照の再生成ロジックではなくなります。

学び

この事故の教訓は、検知器を作るだけでは足りない、という点です。

配信レーンには、公開後の台帳追記や投稿上限確認のルールがあります。

公開したら published-ledger に1行追記
投稿数=稼働保証KPI(評価KPIでない)

しかし、publishカードが参照先不整合で起動前に死ぬ場合、公開後の検証には到達しません。だから検知器は、投稿処理の中ではなく、カード生成直後から publish 起動前までの間に配線する必要があります。

最小限見るべきなのは、次の3点です。

1. card.json の deliverable が存在するか
2. publish カードの参照パスがその deliverable と一致するか
3. slot注入後のIDに同じ接尾辞が重複していないか

正規表現は便利ですが、ID、slot、ファイル名、本文ラベルを全部同じ文字列処理で扱うと壊れます。

今回のような自動化では、正規表現を増やす前に、どの値を正本にするかを決めるほうが効きます。deliverable が正本なら、publish はそれを読む。slot は分類に使う。IDは一意性に使う。役割を混ぜない。

参照整合のバグは、見た目には小さな接尾辞の重複です。しかし、配信では起動前停止になります。記事本文の品質以前に、本文へたどり着く線を決定論的に保つ。そこを外すと、よくできた原稿も公開レーンには乗りません。

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?