A3roプロジェクトでは、AIエージェントと共に記事を執筆しています。 彼らは非常に優秀ですが、時折「人間離れしたミス」や「独特な癖」を見せることがあります。

これらを人間が目視でレビューするのは非効率です。 そこで、記事が公開(Publish)される直前に自動で品質チェックを行う「オレオレLinter」をPythonで実装しました。

なぜ textlint ではないのか

Markdownの校正ツールとしては textlint が有名です。 しかし、今回は以下の理由からPythonによるスクラッチ実装を選びました。

  1. 環境の統一: タスクランナー(manager.py)がPythonで書かれているため、依存関係を増やしたくなかった。
  2. 特殊な要件: 「AIっぽい表現(AI-ism)」の検出や、「特定記号のレンダリング崩れ防止」など、汎用的なルールではカバーしきれない要件があった。
  3. リンク生存監視: 記事内の外部リンクが生きているか(404になっていないか)を、Publishのタイミングで同時にチェックしたかった。

Linterの機能

実装した lint.py は、以下の3つのチェックを行います。

1. Markdownレンダリング保護

AIエージェントは時々、強調記法(**)と日本語の括弧()の順序を間違えます。

  • NG: ** 「強調したい文字」 ** (ブラウザによってはアスタリスクが露出する)
  • OK: 「**強調したい文字**」

これを正規表現 re.search(r'\*\*([「『])', content) で検出し、エラーとして弾きます。

2. AI-ism(AIらしさ)の排除

AIが生成する文章には特有の「硬さ」があります。 特に「これ により(As a result of this)」という接続詞は、文脈によっては不自然に響くことがあります。

A3roでは、より自然な日本語を目指すため、この単語が含まれている場合に警告を出すようにしました。

3. 外部リンクの死活監視

記事の信頼性を担保するためには、貼られたリンク先が存在していることが重要です。 Pythonの標準ライブラリ urllib.request を使い、記事内の全ての外部URLに対して HEAD リクエストを送信し、ステータスコードをチェックしています。

ワークフローへの統合

このLinterは、デプロイ用スクリプト manager.py に統合されています。

# Publishコマンドを実行すると...
python manager.py publish my-article.md

# 裏側で lint.py が走る
Linting 'my-article.md'...
[PASS] All checks passed.

# チェックに通れば公開処理へ進む
Publishing...

この仕組みのおかげで、CI/CDツールを導入せずとも、ローカルでの作業フローの中に「品質の門番」を置くことができました。 「汚いコード(文章)は本番環境に入れない」。これはソフトウェア開発の鉄則であり、ブログ執筆でも同じです。