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?

AI導入の変更後に再確認日を決める:GASで変更イベントと確認期限を管理する

0
Posted at

AIの対象業務や確認ルールを変更した後、「いつ、誰が、何を確認するか」が決まっていないと、古い判断がそのまま使われます。

この記事では、GoogleスプレッドシートとGoogle Apps Script(GAS)で、変更イベントから再確認日を計算し、確認待ちの一覧を作る最小構成を紹介します。GASが導入可否や顧客影響を判断する仕組みではありません。期限の設定と候補の抽出までを補助し、再確認・承認・停止解除は人が行います。

作るもの

AI導入の変更後に人間確認へ戻す境界

AI_CHANGE_REVIEWS シートに、変更一件を一行で記録します。

review_id,work_id,change_type,changed_at,impact_level,
source_ref,review_owner,review_due_at,review_state,
exception_rule,next_action,last_reviewed_at

change_type は、たとえば次のように固定します。

RULE       # 判定・プロンプト・確認ルールの変更
SOURCE     # FAQ、手順書、正本データの変更
INPUT      # フォームやCRMの入力項目の変更
OWNER      # 担当者・確認者・代理の変更
EXCEPTION  # 例外や停止条件の追加・変更

再確認日を決める6項目

変更があった日だけでなく、影響と確認者を記録します。

項目 記録する内容 例
変更イベント 何が変わったか FAQの回答条件を更新
変更日時 現行版が有効になった日時 2026-10-06 09:00
影響度 通常・境界・停止のどこに影響するか 境界
正本 比較する現行資料 FAQ v4
確認者 業務の判断をする役割 サポート責任者
再確認日 人が見直しを始める日時 2026-10-08 09:00

再確認日は「その日に自動で新ルールへ切り替える日時」ではありません。変更の影響を人が確認する開始日時です。

先に状態を固定する

変更後の案件は、次の3状態に分けます。

CONTINUE   # 変更の影響がなく、通常の確認で進められる
REVIEW     # 影響する可能性があり、人が再確認する
HOLD       # 情報不足・重大な影響・確認者不在で手動へ戻す

期限が来たから CONTINUE に移す処理は作りません。REVIEW または HOLD のまま、確認者が根拠を見て状態を更新します。

GASで入力値を検査する

まず、見出しと状態を検査します。シート名や値をコードに固定しすぎず、入力ミスを早く見つけることを目的にします。

const SHEET_NAME = 'AI_CHANGE_REVIEWS';
const REQUIRED_HEADERS = [
  'review_id', 'work_id', 'change_type', 'changed_at', 'impact_level',
  'source_ref', 'review_owner', 'review_due_at', 'review_state',
  'exception_rule', 'next_action', 'last_reviewed_at'
];
const REVIEW_STATES = ['CONTINUE', 'REVIEW', 'HOLD'];
const CHANGE_TYPES = ['RULE', 'SOURCE', 'INPUT', 'OWNER', 'EXCEPTION'];

function validateChangeReviews() {
  const sheet = SpreadsheetApp.getActive().getSheetByName(SHEET_NAME);
  if (!sheet) throw new Error(SHEET_NAME + ' sheet is missing');

  const values = sheet.getDataRange().getValues();
  if (values.length === 0) throw new Error('header row is missing');
  const headers = values.shift().map(String);
  const index = Object.fromEntries(headers.map((name, i) => [name, i]));
  const missing = REQUIRED_HEADERS.filter((name) => index[name] === undefined);
  if (missing.length) throw new Error('Missing headers: ' + missing.join(', '));

  const errors = [];
  values.forEach((row, offset) => {
    if (row.every((cell) => cell === '')) return;
    const line = offset + 2;
    const state = String(row[index.review_state] || '');
    const changeType = String(row[index.change_type] || '');
    const dueAt = row[index.review_due_at];

    if (!CHANGE_TYPES.includes(changeType)) {
      errors.push('row ' + line + ': invalid change_type');
    }
    if (!REVIEW_STATES.includes(state)) {
      errors.push('row ' + line + ': invalid review_state');
    }
    if (!String(row[index.review_owner] || '').trim()) {
      errors.push('row ' + line + ': review_owner is required');
    }
    if (!dueAt || Number.isNaN(new Date(dueAt).getTime())) {
      errors.push('row ' + line + ': review_due_at is required');
    }
    if (state !== 'CONTINUE' && !String(row[index.exception_rule] || '').trim()) {
      errors.push('row ' + line + ': exception_rule is required');
    }
  });

  if (errors.length) throw new Error(errors.join('\n'));
  return {ok: true, rows: values.length};
}

変更から再確認日を計算する

最初は影響度ごとに確認間隔を決めます。日数は会社の業務特性に合わせて変更してください。ここで行うのは日付の候補作りであり、確認の完了ではありません。

const REVIEW_INTERVAL_DAYS = {
  normal: 7,
  boundary: 2,
  stop: 0
};

function suggestReviewDueAt(changedAt, impactLevel) {
  const level = String(impactLevel || '').toLowerCase();
  if (!(changedAt instanceof Date) || Number.isNaN(changedAt.getTime())) {
    throw new Error('changedAt must be a valid Date');
  }
  if (REVIEW_INTERVAL_DAYS[level] === undefined) {
    throw new Error('unknown impact level: ' + impactLevel);
  }

  const due = new Date(changedAt.getTime());
  due.setDate(due.getDate() + REVIEW_INTERVAL_DAYS[level]);
  return due;
}

stop を0日にしているのは、停止条件に該当する変更を後回しにしないためです。ただし、0日になった行を自動再開させず、必ず HOLD として人へ戻します。

確認期限が来た行を一覧化する

期限を過ぎた行の next_action を更新します。状態を進めないため、時間主導トリガーで毎朝実行しても導入範囲は変わりません。

function listDueReviews() {
  const sheet = SpreadsheetApp.getActive().getSheetByName(SHEET_NAME);
  const values = sheet.getDataRange().getValues();
  const headers = values.shift().map(String);
  const index = Object.fromEntries(headers.map((name, i) => [name, i]));
  const now = new Date();

  return values.flatMap((row, offset) => {
    const dueAt = new Date(row[index.review_due_at]);
    const state = String(row[index.review_state] || '');
    if (!['REVIEW', 'HOLD'].includes(state) || dueAt.getTime() > now.getTime()) {
      return [];
    }
    return [{
      row: offset + 2,
      reviewId: String(row[index.review_id] || ''),
      owner: String(row[index.review_owner] || ''),
      nextAction: '変更の影響を確認し、根拠と状態を人が更新する'
    }];
  });
}

通知を追加する場合も、メールやチャットへ顧客本文を含めず、review_id と確認先だけを送ります。

変更後の確認手順

  1. 変更ID、有効日時、旧版、現行版を正本から確認する
  2. 変更境界の前後で処理された案件を候補化する
  3. 通常・境界・停止の1件ずつを選ぶ
  4. 入力情報、参照先、承認状態、外部送信の有無を人が確認する
  5. CONTINUE、REVIEW、HOLD と根拠を記録する
  6. FAQ、フォーム、承認ルール、手動キューの改善先を更新する

自動化しない境界

  • 顧客への返信や外部送信の最終判断
  • 契約、料金、返金、法的な権利義務の判断
  • 個人情報・機密情報をAIへ渡してよいかの判断
  • HOLD からの自動再開、確認者不在時の代理承認
  • 重大な苦情や安全上の問題がある案件の継続

迷う場合は HOLD にして、原文を扱える担当者と手動の戻し先を記録します。シートには顧客本文やメールアドレスをコピーせず、権限管理された原本の参照先だけを置きます。

まとめ

AI導入の変更後に必要なのは、変更を告知することだけではありません。

  1. 変更イベントと有効日時を固定する
  2. 影響度、正本、確認者、再確認日を記録する
  3. 期限を自動再開ではなく、人間レビューの候補化に使う
  4. 通常・境界・停止のケースを確認する
  5. 判断結果をFAQ、フォーム、承認ルールへ戻す

まずは直近の変更一件を AI_CHANGE_REVIEWS に登録し、再確認日を決めてください。Miraigentでも、AIを広げる前に「変更後、次はいつ誰が見るか」を確認することを、運用診断の入口にしています。

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?