コンテンツにスキップ

Goal を使って textlint のエラーを直す

当ブログでは、Markdown で書いた記事の文章を確認するために textlint(文章の自動チェックツール)を使っています。しかし、textlint が検出したエラーの対応を長期間放置していたのが実情でした。そこで AI coding agent である OpenAI の Codex CLI の/goalコマンドを使い、npx textlint article/の終了コード 0 を完了条件として修正を進めました。

取り組みの方針

今回の作業では、ルールを全体無効化せずに textlint を通す進め方が要点です。ルールの挙動を調べ、例外を必要な箇所だけに限定し、本文そのものも確認します。こうした作業条件を/goalに明示しておくと、文章を直すか設定を変えるかを、エラーが消えるかどうかだけでなく、この条件に照らして判断できます。

引用文を変更せず、文書全体の分析を有効にしたまま、最終的にnpx textlint article/を成功させました。textlint では見つけにくい文体の混在には、リポジトリ内の作業用スクリプトも活用しました。

今回の Goal

エージェントに指定した Goal は次のような内容です。

1
2
3
/goal
`article/`内の Markdown を、`npx textlint article/`が成功するまで改善したい。
ルールを全体で無効化せず、引用を変更せず、本文の意味と事実関係も確認して進めてください。

/goalは、エージェントに達成すべき目標を指示するコマンドです。「文章を改善する」という曖昧な依頼だけでは、どこまで直せば終わりか分からないため、npx textlint article/の終了コード 0 を作業の完了基準にしました。

終了条件だけでなく、やってはいけないことも一緒に指定しておくと、意図しないルールの無効化を防げます。

ルール設定の見直し方針

textlint の検査を無効化・除外することを、ここでは skip と呼びます。設定上は、次の 3 種類を区別します。

  • ルール全体の無効化:textlint の設定ファイル.textlintrcでルールをfalseにする
  • 範囲の無効化:本文にtextlint-disableとtextlint-enableを書く
  • パターン単位の例外:ルールのallowsに一致条件を設定する

ルールを無効化するだけであれば目の前のエラーは消えます。しかし、無効化だけでは将来の記事で同じ問題が発生しても検出できません。

そこで、次のような観点を持って修正の妥当性を確認しました。

  • lint を通すためだけにルールを安易に無効化していないか
  • 自動修正で意味や事実関係が変わっていないか
  • サンプルを実測結果のように断定して書いていないか
  • 引用と著者の説明を混同していないか

引用のように原文を改変できない箇所は、ルール全体を skip せず、引用段落だけに例外を限定します。

意図的に無効化(skip)のまま維持したルールと、再び有効にしたルールは次のとおりです。

対応 ルール 理由
無効化を維持 sentence-length 標準プリセットのこのルールは、技術文書向けルールの 150 文字制限と役割が重複する
無効化を維持 ja-no-mixed-period 注意書きなど句点を付けない構造で誤検出しやすい
再び有効化 no-doubled-joshi / max-ten / ja-no-weak-phrase 同じ助詞の重複、読点の数、弱い表現は文章側の見直しで対応できる

エラーの内容を確認する

npx textlint article/を実行して、実際に textlint が報告するエラーを確認しました。

1
2
3
4
article/github-actions-secret.md
  1:1  error  【テクニカルライティング品質分析】この文書で改善提案が見つかりました  @textlint-ja/ai-writing/ai-tech-writing-guideline

✖ 4 problems (4 errors, 0 warnings, 0 infos)

報告内容は、説明を具体化し、冗長な表現を簡潔にするという提案でした。エラーが複数の記事で文書の先頭(1:1)に表示されていたのは、文書全体を分析するルールのサマリーだったためです。

4 件とも、引用段落の個別チェックを無効にしてある記事で、文書全体のサマリーとして出ていました。

ルールの挙動を調べる

該当する 4 記事には、公式ドキュメントからの引用が含まれていました。引用部分には次のようなコメントを付けて、AI ライティングルールの個別チェックを無効にしていました。

1
2
3
<!-- textlint-disable @textlint-ja/ai-writing/ai-tech-writing-guideline -->
> 公式ドキュメントからの引用
<!-- textlint-enable @textlint-ja/ai-writing/ai-tech-writing-guideline -->

原因を調べたところ、textlint-disableが抑制するのは個別のインライン警告で、該当ルールが持つ文書全体の集計(enableDocumentAnalysis)までは停止しないと分かりました。

enableDocumentAnalysisをfalseにすればエラーは消えますが、文書全体の品質分析も失われてしまいます。今回の目的は分析を止めることではなく、引用箇所だけを集計から除外して、自分の文章を適切に検査することです。

引用を守りながら設定を直す

引用文を改変せず、文書サマリーも有効にしたまま通すため、AI ライティングルールのallows設定項目を活用しました。allowsに指定したパターンと一致する段落は、エラー報告の対象外になります。

.textlintrcには、引用段落の先頭に一致する正規表現を登録しました。

1
2
3
4
5
6
"ai-tech-writing-guideline": {
    "allows": [
        "/^アプリケーションをローカルで開発して/"
    ],
    "enableDocumentAnalysis": true
}

単語単位で許可すると、通常本文の記述まで検査をすり抜けてしまいます。そこで、^で段落の先頭を指定し、該当する引用段落にのみ一致するようにしました。

本文の推敲

設定変更だけでなく、本文の記述自体も見直しました。機械的な一括置換を避け、文脈と事実関係を確認しながら修正しました。

サンプルと結論の混同の解消

一部のサンプルから全体を断定している表現は、次のように範囲を限定しました。

修正前:このサンプルでサービス全体を評価できます。
修正後:このサンプルは、サービス全体を考えるための一つの材料です。

記事の対象範囲の適正化

短い手順メモに対して「詳しく解説する」と表現するなど、タイトルや導入が実際の内容を超えてしまうケースがあります。そうした表現を確認し、控えめで正確な表現に改めました。

ファイル内の文体混在の確認

textlint のチェックを通過した場合でも、同一ファイル内で文体が混在していることがあります。no-mix-dearu-desumasuルールは段落単位で判定するため、導入部と後半で文体が違うケースを見逃すことがあります。たとえば、導入部が「です・ます調」で、後半だけ「である調」になっている記事です。

そこで、文体の統一候補を検出する検証スクリプトscripts/find-desumasu-candidates.mjsをリポジトリ内に追加しました。追加した時点の検査対象は次のとおりです。

  • 検査対象:通常本文の段落
  • 除外対象:見出し、コードブロック、引用、表

機械的な自動置換は行わず、候補を目視確認した上で本文の文体を統一しました。文体統一の検証をリポジトリで継続して再現できるよう、package.jsonにlint:styleスクリプトとして登録しています。

結果

設定と本文の修正後、改めて検査コマンドを実行しました。

npx textlint article/

出力はなく、終了コードは 0 でした。enableDocumentAnalysis: trueを維持したまま、引用文の改変やルールの全体無効化を行わずに成功条件を満たせました。

補足:使用したモデル

今回の作業ループには GPT-5.6 Luna を使用しました。リポジトリ全体を読み込みながら短い修正とコマンド再実行を繰り返す反復タスクだったため、トークン費用の安さとレスポンス速度を基準にモデルを選定しています。

まとめ

今回の作業を通じて、AI coding agent に校正や修正を依頼する際は「作業の終了条件」と「禁止事項」をセットで与えることが重要であると分かりました。

「エラーを解消して」とだけ指示すると、ルールを無効化する安易な解決策が選ばれがちです。終了条件のコマンドを指定し、ルール無効化の禁止や事実関係の保持を明記することで、設定の見直しと文章自体の改善を両立できます。

参考