A3roプロジェクトでは、AIエージェントと共に記事を執筆しています。 彼らは非常に優秀ですが、時折「人間離れしたミス」や「独特な癖」を見せることがあります。
これらを人間が目視でレビューするのは非効率です。 そこで、記事が公開(Publish)される直前に自動で品質チェックを行う「オレオレLinter」をPythonで実装しました。
なぜ textlint ではないのか
Markdownの校正ツールとしては textlint が有名です。
しかし、今回は以下の理由からPythonによるスクラッチ実装を選びました。
- 環境の統一: タスクランナー(
manager.py)がPythonで書かれているため、依存関係を増やしたくなかった。 - 特殊な要件: 「AIっぽい表現(AI-ism)」の検出や、「特定記号のレンダリング崩れ防止」など、汎用的なルールではカバーしきれない要件があった。
- リンク生存監視: 記事内の外部リンクが生きているか(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ツールを導入せずとも、ローカルでの作業フローの中に「品質の門番」を置くことができました。 「汚いコード(文章)は本番環境に入れない」。これはソフトウェア開発の鉄則であり、ブログ執筆でも同じです。