name: audit-test-design-skill description: audit query / IDB rule の test を 会計・税務・労務・内部統制 の 観点 で 設計する スキル。 境界値 / 反例 / サンプリング / positive-negative pair / 走行結果 4 区分 (TP/TN/FP/FN) を 揃えて 業務知識 + DataLog 挙動 の 両軸 で 「適切な test 集合」 を 提案する。 datalog_testcase_create / datalog_testrecord_propose を 呼ぶ 直前 に 参照。

Audit Test Design Skill

audit query (= 監査クエリ) / IDB rule の test を 業務知識 + DataLog 挙動 の 両軸 で 設計する 専用 skill。 datalog-debug-skill の §5 (= test 駆動 lifecycle) が 基本 lifecycle (= scope 別 必須件数 / dual content / status 4 値) を カバー する 一方、 本 skill は 「何を test するか / どう サンプリング するか / どの 境界値 を 押さえるか」 に 集中。

LLM が datalog_testcase_create / datalog_testrecord_propose を 呼ぶ 直前 に 本 skill を 参照し、 test 集合 が:

  • 業務上 の boundary を 全方向 (= 上 / 境界 / 下 / 大幅) 押さえる
  • positive と negative の 対 (twin) が 揃う
  • null handling / multiEntity / edgeCase の カバレッジ がある
  • 全件 dump で なく 適切な サンプリング で 検証 反復性 を 保つ

ことを 確認する。


0. dataSource (= 検証様式) は 必須・明示宣言 (#535)

すべての TestCase は dataSource必ず明示する。 runtime 導出 (= testRecords から自動推測) は 廃止。 作成時に作者が下表から 1 つを選び宣言する (schema が required で強制し、 未指定は parse で reject)。

dataSource いつ 追加 field
freee_e2e 検出対象を freee に実投入できる 監査 test (= testRecords で freee 投入 → e2e 走行) (なし)
datom_only 検出対象を freee に作れない ゆえ datom 単体で完結する完成形 (= e2e 不要、 passing が terminal green) e2eBlockedReason 必須 + e2eBlockedDetail 推奨

datom_onlye2eBlockedReason (= なぜ freee に作れないか / 対象でないか):

reason 意味
freee_required_field_missing 必須欄 (account_item / tax_code / issue_date 等) を欠落させて作れない (400)
freee_readonly_derived read-only 派生値 (月次勤怠 等) を任意値で合成できない
freee_demo_constraint デモ会社 / 権限制約で作れない (従業員 0 / HR 403)
freee_api_unsupported 合成 POST 経路が無い (origin 手動固定 等)
not_freee_target freee 検出対象でない純論理 IDB rule test (= idb rule の導出検証。 freee 投入と無関係)

判定: 「この検出対象を freee 上に作れるか?」→ 作れる=freee_e2e / 作れない=datom_only+理由 / そもそも freee と無関係の純論理 IDB rule=datom_only+not_freee_target。 UI では datom_only は投入/e2e ボタンが不感化される (= 純論理/作成不能テストで正しい挙動)。

1. TestCase tags (= 観点 別 分類)

TestCase.tags は array で 複数 選択。 各 tag は 意図 + few-shot で 揃えて 使う。

tag 意図 few-shot 観点
happyPath 正常系 (= 違反 と すべきでない 標準 case) 通常の deal で 全 必須項目 揃い
boundary 条文 / 規定 の 閾値 上 で の 判定 30000 円 ぴったり / 45 時間 ぴったり
edgeCase 業務上 の レア case 0 円 取引 / 巨大金額 / 同日 多重 計上 / 過去 年度 修正
nullHandling 必須 attr が 欠落 取引先 null / 税コード null / 期日 null
errorHandling エラー 経路 freee API 取得 失敗 / 必須 entity 不在
dataIntegrity 参照 整合性 借方=貸方 不一致 / 親 deal 不在 の detail
multiEntity 複数 entity 連結 deal + detail + partner + account_item の 4 階層 揃い vs 1 欠け
regression rule 改修時 の 既存挙動 維持 過去 全 query で passing を 復活 確認
historicalBug 過去 incident の 再発防止 「2024 Q3 に partner null を 拾い損ねた 事例」

複数 tag 重ね OK (= 「boundary + nullHandling」 等)。


2. 境界値 (= boundary) table — 会計・税務・労務 / 内部統制 別

audit query が 触る ドメイン 別 に、 法令 / 規程 の 「閾値」 を 列挙。 LLM は 該当 ドメイン の boundary を 必ず test に 入れる。

消費税 (= 仕入税額控除 / 売上 / 課税区分)

boundary 根拠 / 文脈 test 例
インボイス T番号 有無 適格請求書 発行事業者 登録 T番号 あり vs なし vs 形式不正
経過措置 控除割合 2023-09 〜 2026-09: 80% / 2026-10 〜 2029-09: 50% 期間 跨ぎ の 控除割合 切替
税区分 4 値 課税仕入 / 課税売上 / 非課税 / 対象外 各 値 1 件
軽減税率 8% / 10% / 0% (= 輸出) 各 税率 で の 集計

法人税 / 損金算入限度

boundary 根拠 / 文脈 test 例
交際費 損金 限度 中小法人 800 万円 / 上位 50% / 0% 限度直前 / 直後
寄付金 損金 限度 一般 / 特定 / 国等 別 限度 計算式 境界
役員 報酬 定期 同額 月額 一定 (= 不定期 改定 は 損金 不算入) 改定 タイミング 境界

電帳法 (= 電子帳簿保存法、 2024 改正)

boundary 根拠 / 文脈 test 例
電子取引 発生源 銀行 明細 / カード明細 / メール添付 PDF / 経費申請 等 = 電子保存 必須 各 発生源 で 証憑 有 vs 無
紙 受領 紙 領収書 は 電帳法 対象外 (= 別途 国税関係 書類 保存) 発生源 = 紙 で 証憑 無 → 拾わない
スキャナ保存 タイムスタンプ 撮影 から 3 日 以内 境界 タイミング

36 協定 / 労働基準法

boundary 根拠 / 文脈 test 例
法定外労働 月限度 45 時間 / 月 44h / 45h / 45h+1min / 60h
法定外労働 年限度 360 時間 / 年 月 平均 30h 累積 / 後半 集中
特別条項 月限度 100 時間 (= 単月) / 80 時間 (= 2-6 ヶ月 平均) 単月 99h vs 100h vs 101h
特別条項 年限度 720 時間 / 年 累積 境界
健康福祉 確保措置 80h/月 超 で 医師 面談 等 80h 境界 + 措置 有無

内部統制 / 社内規程

boundary 根拠 / 文脈 test 例
高額 取引 承認 30000 円 / 100000 円 / 1M 円 (= 社内 規程 次第) 各 閾値 ± 1
役員 取引 利益相反 役員 + 役員 親族 / 役員 関連会社 取引先 属性
締日 跨ぎ 取引 月末 / 期末 計上 月 切替

会計帳簿 必須項目

boundary 根拠 / 文脈 test 例
発行日 法人税法 施行規則 第54条 発行日 有 vs 無
取引先 消費税法 第30条第7項 (= 課税仕入 のみ) partner 紐付け 有 vs 無 vs 親 deal 経由
勘定科目 仕訳 必須 account_item null vs 設定済
借方 / 貸方 一致 複式簿記 原則 不一致 額 1 円 vs 0 円
税コード 消費税申告 集計用 tax_code null vs 設定済

3. test サンプリング 戦略

全件 (= 数千件) を test に 入れない。 サンプリング 必須項目:

必須サンプル ルール

  1. 各 boundary に対し 4 件: 下 / 境界 / 上 / 大幅 上 (= 「44h / 45h / 45h+1min / 60h」 / 「29999 / 30000 / 30001 / 100000」)
  2. 各 必須項目 に対し 2 件: 存在 / null
  3. 各 enum 値 に対し 1 件: 全 列挙 (= 税区分 4 種 / 取引種別 2 種 / 決済状態 2 種)
  4. multiEntity で 「全 階層 揃い」 + 「1 階層 欠け」 の 2 件

避ける パターン

  • 全 freee row の dump (= 大規模 / 流動的 / 検証 反復性 を 失う)
  • 1 件 だけの test (= 偶然 通る ケース で 過剰 検出 / 漏れ を 区別 できない)
  • 同じ boundary を 異なる データ で 5 件 重複 (= 1 件 で 十分、 多様性 が ない)
  • 期間 跨ぎ や 期日 を 含む test に 「現在 日時」 を 直書き (= 時間 経過 で 結果 が 変わる、 固定 日付 を 使う)

4. positive / negative 対 (= twin test)

各 boundary に対して 必ず positive + negative の pair を 作る。

  • positive (= 「拾うべき」): boundary を 超えた / 違反 case → audit query が runStatus='passing' で 検出 する
  • negative (= 「拾うべきでない」): boundary 直前 / 適合 case → audit query が 検出 しない

二極化 が 揃ってない と:

  • positive のみ → false negative (= 検出 漏れ) を 検知 できない
  • negative のみ → false positive (= 過剰 検出) を 検知 できない

例: 36 協定 (boundary = 45h):

kind datoms expected
positive excess_statutory_mins = 2701 (= 45h + 1min) hit
positive excess_statutory_mins = 3600 (= 60h、 大幅 超) hit
negative excess_statutory_mins = 2700 (= 45h ぴったり) not-hit
negative excess_statutory_mins = 2699 (= 45h - 1min) not-hit

5. 走行結果 4 区分 (= TP / TN / FP / FN)

走行後 runStatus + actualHits から 4 区分 を 計算:

期待 拾う (= positive) 期待 拾わない (= negative)
実 拾う truePositive (= TP、 期待通り) falsePositive (= FP、 過剰検出 = audit query が 厳しすぎ)
実 拾わない falseNegative (= FN、 検出漏れ = audit query が 緩すぎ) trueNegative (= TN、 期待通り)

datalog_testrecord_listbyKindRunStatus で 集計可能。

判断:

  • FP / FN が 0 件 = audit query OK
  • FP が ある = audit query を 厳しく 改修 (= 条件 追加 / 閾値 上げ) or test を 修正
  • FN が ある = audit query を 緩く 改修 (= 条件 削除 / 閾値 下げ) or test を 修正
  • どちら 修正 か は 「業務 規程 が どう か」 から 決める (= test が 業務 真理、 audit が 仮説、 と 思って 改修)

5.5 failing 時 の 意思決定モデル (= 何を真とみなし、 どう直すか)

§5 の「FP→厳しく / FN→緩く」 は 単発 の 局所処方。 ここでは 「failing を前にした時の判断順序」 を 規定する。 順序自体が FN 優先思想を体現する。

最重要原則 (= 常に先に思い出す)

迷ったら TP に倒す (= FN を作らない、 検出する方向)。 決定不能なら warning に降格して人へ渡す (= FN も作らず歪めもしない)。 FP は アクション 4 で後から削れる。 failing を消すこと自体を目的化しない — クエリを期待値に寄せる / 期待値をクエリに合わせて緩める のは、 決定論と説明可能性をシステム内部から腐らせる。

意思決定木

問い0: 単発の failing か、類型内の散らばりか?
  └ datalog_testrecord_list の byKindRunStatus を 類型単位 で 見る。
     特定類型で FP と FN が両立 → 散らばり → §5.6 へ
     単発 → 問い1へ
  ※ 散らばりは個々のテスト行では気づけない。集計ビューで初めて見える。

問い1: そもそも datalog で決定的に判定できる種類の違反か?
  └ 判断境界・規範解釈・事実認定が絡む (外注費か給与か、 交際費か会議費か 等)
     → 否なら即 A5a (warning 降格、 人へ)。 クエリを歪めず FN も作らない。
     → 是なら問い2へ

問い2: 食い違いは FN型 か FP型 か?
  ├ FN型 (期待 TP・なのに検出されず = 取りこぼし) = 最優先で潰す
  │   切り分け: 期待値が誤り→A1 / fixture が誤り→A2 / クエリが狭すぎ→A3 (主力)
  │   迷ったら TP に倒す
  └ FP型 (期待 TN・なのに検出 = 過剰) = 急がない。 常に FN 対応の後
      クエリが広すぎる→A4 で精緻化 / 期待値の誤解→A1

5 アクション (= 取りうる対応)

アクション datalog で対応? user 協調 FN 優先での位置づけ
A1 期待値修正 (what) 否 (what 層、 クエリは正しい) 必須: _propose→user _approve。 LLM 単独で書換禁止 (= 期待値は監査基準 SOR) FN 局面で期待値を緩めて見逃しを消すのは思想違反。 特に慎重に
A2 入力データ修正 (fixture/data) 否 (data 層、 特に e2e で投入シナリオが意図構造にならない時) 必須: 業務知識者に実務上のデータ形を確認、 原票 (freee 画面) で診断 fixture の歪みを除去して 4 区分の信頼性を回復
A3 クエリ修正 (how・正攻法) (datalog_query_update) 低 (LLM 主導)。 広げると FP 増 → 後で A4 で削る FN 潰しの主力。 迷ったら TP 側に倒す
A4 クエリ追加 (how 拡張・精緻化) 是 (IDB 述語 / サブ条件追加、 既存は壊さず多層化) 中: error/warning の境界を user に諮る A3 で FN 潰した後の増分 FP を削る (=「FP はいくらでも調整できる」の実体)
A5a ケース単位の降格 否 (明示放棄、 信頼度 error→warning) 最も協調的: 決定を人へ返す FN の安全弁。 歪めず・見逃さず・人に渡す

e2e 失敗 と datom_only 失敗 の 診断差

  • datom_only 緑 × e2e 赤 = ルール (how) でなく freee 同期境界の問題 (= 投入シナリオ / 同期パイプラインが意図構造にならない)。 → A2 (fixture/同期) を疑う。 クエリ (A3/A4) を触らない。
  • e2e_passing (40) の手前 (= passing だが e2e 未到達) で止まっている時は、 testRecords の freee 投入結果を先に診断する。

5.6 「類型内の散らばり」 (= 同一類型で TP/TN/FP/FN 混在) の扱い

散らばりを A5a (ケース単位の決定不能) として 一律降格すると、 本来 TP で確実に黒だったものまで warning に落ちる (= FN 優先に反し確実な違反の信頼度を下げる)。 散らばりは「1 ケースがグレー」ではなく「判別境界が母集団分布にうまく引けていない」状態で、 性質が違う。

問い: その散らばりは、 追加の特徴量 (述語) で 分離可能 か、 本質的に分離不能 か?

  • 分離可能: 今は混在だが未使用属性を述語化すれば TP 群 / TN 群 を分けられる (例: 「同一取引先で科目が揺れる」FP が、 実は「継続契約先 / スポット先」で正常異常が分かれていた → 契約区分述語で解ける)。 → A3 で境界を FN ゼロ位置まで広げ、 増分 FP を A4 の追加述語で削る。 散らばりを 4 区分がきれいに分かれる状態へ追い込む。
  • 本質的に分離不能: どんな属性を足しても datalog の見える事実だけでは分けきれない (実態判断・規範解釈が残る)。 → 類型ごと降格 (個別ケースでなく類型全体を warning 化)。 ただし FN 優先で、 該当候補は漏れなく warning で拾う (= 網羅検出ルールは TP 志向で広く張る)。 決定は人、 しかし人の目に乗せる対象は見逃さない。

集合知ループ接続: 散らばりをどう処理したか (述語追加で解いた / 類型降格した) を記録すれば、 「人と datalog の分業境界」 の学習データになる。 分離可能な散らばりの解法は組織の監査ノウハウ、 分離不能な類型は「ここから先は人間」 という境界そのものが資産化される。


6. 既存 test ライフサイクル と の 接続

datalog-debug-skill §5 と 整合:

  • test 提案 (= datalog_testrecord_propose) では 上記 1-5 の 観点 を カバー した 集合 を 提案
  • TestCase 側 の statuteDescription (= 法的根拠 Markdown、 #406) も 同時に 埋める
  • statuteDescription (audit query 側、 #396) と TestCase 側 を 対応させて 「この test が 検証する 法 / 規程」 を 明示
  • run 後 FP / FN が あれば audit query 改修 or test 修正 を datalog_testrecord_request_change 経由で 提案

7. Few-shot 例 (= LLM 出力 参照用)

例 A: 36 協定 (overtime_36agreement) の test set

監査クエリ: 法定外労働 > 2700 分/月 を error として 検出。

TestCase tags datoms (= 月次勤怠) expected
ぴったり 45 時間 → 拾わない boundary, happyPath excess_statutory_mins = 2700 not-hit
45 時間 + 1 分 → 拾う boundary excess_statutory_mins = 2701 hit
大幅超 60 時間 → 拾う boundary excess_statutory_mins = 3600 hit
法定外労働 属性 不在 → 拾わない nullHandling excess_statutory_mins = null not-hit
特別条項 適用 (= 別 ルール) → 拾わない edgeCase excess_statutory_mins = 4800、 special_clause = true not-hit

→ 5 件 で 「上 / 境界 / 下 / null / 例外」 を カバー。

例 B: 高額取引 証憑 (high_amount_no_receipt) の test set

監査クエリ: amount ≥ 30000 円 で has_receipt = false を warning として 検出。

TestCase tags datoms (= deal) expected
30000 円 + 証憑 なし → 拾う (境界) boundary amount = 30000, has_receipt = false hit
30001 円 + 証憑 なし → 拾う boundary amount = 30001, has_receipt = false hit
29999 円 + 証憑 なし → 拾わない boundary, happyPath amount = 29999, has_receipt = false not-hit
30000 円 + 証憑 あり → 拾わない happyPath amount = 30000, has_receipt = true not-hit
100000 円 + 証憑 なし → 拾う (= 大幅超) edgeCase amount = 100000, has_receipt = false hit

→ 5 件 で 「境界 ぴったり / +1 / -1 / 証憑 切替 / 大幅超」 を カバー。

例 C: 課税仕入 取引先 (taxable_purchase_no_partner) の test set

監査クエリ: 課税仕入 明細 + 取引 / 明細 どちら にも 取引先 紐付け 無し で warning。

TestCase tags datoms (= deal + detail + partner) expected
課税仕入 + 取引先 紐付け 無し → 拾う boundary detail.tax = 'taxable_purchase', deal.partner = null, detail.partner = null hit
課税仕入 + 取引 自体 に 取引先 → 拾わない multiEntity detail.tax = 'taxable_purchase', deal.partner = partner_1, detail.partner = null not-hit
課税仕入 + 明細 自身 に 取引先 → 拾わない multiEntity detail.tax = 'taxable_purchase', deal.partner = null, detail.partner = partner_1 not-hit
課税仕入 2 件 (1 件 紐付け / 1 件 無し) → 1 件 拾う edgeCase, multiEntity detail_1.partner = partner_1, detail_2.partner = null hit (detail_2 のみ)
課税売上 で 取引先 無し → 拾わない (= ルール 範囲外) happyPath detail.tax = 'taxable_sales', deal.partner = null not-hit

→ 5 件 で 「主条件 / 取引 経由 補完 / 明細 経由 補完 / 部分 hit / ルール 範囲外」 を カバー。


8. test 出力 形式 (= datalog_testrecord_propose 呼出し 時)

datalog_testrecord_propose({
  testCaseId: 'tc_xxx',
  proposal: {
    // datoms = 試行 input (= 必要 entity を 揃える)
    datoms: [
      [{ 'node/id': 'work_record_1', 'attr/excess_statutory_mins': 2701, ... }],
      // ... 関連 entity も 含める
    ],
    // expectedRows = 期待 出力 (= 該当 query を 走らせた 結果)
    expectedRows: [['work_record_1']], // positive
    // expectedRows = [] // negative
    // kind: 'positive' | 'negative' は TestCase header 側
    statuteDescription: '...', // #406 連動、 法的根拠 Markdown
  },
});

複数 test (= boundary 揃い) を 提案する 場合、 1 件 ずつ propose を 呼ぶ。 タグ + statuteDescription で 「なぜ この case か」 を 明示。


9. test 実装 4 phase (= 段階追い、 #412)

test は 最終 e2e (= freee 投入 + 実走行) まで が 完成形 だが、 段階を 追って runStatus で 進捗を 表現 できる。 LLM は 1 phase 終了 ごとに status を 明示更新 して、 user / 別 LLM が 続きを 引き継げる ように する。

Phase 出力 TestCase.runStatus TestRecordV2
1. 概要 設計 TestCase header (= title / userDescription / why / statuteDescription / kind / tags) test_design_pending (7) 0 件
2. 期待 列挙 hit 対象 row (= nodeKey + expectedKind={TP,TN} + label + userDescription) + 関連背景 row (= nodeKey + expectedKind=outOfScope) test_design_pending (7) or failing (20) N > 0 件、 datoms 任意
3. データ詰め datoms (= 走行入力 fact)、 業務期待値 (= businessExpectation。 LLM は draft ordinal のみ書込可) passing (30) datoms あり
4. e2e freee 投入 (= freeeReqBody / freeeKind) → 実走行 → resultKind 観測 e2e_passing (40) freeeReqBody + lastSyncedAt あり

Phase 1 の 詳細

  • TestCase header は 走らせない (= 仕様 だけ) → runStatus = test_design_pending
  • 親 audit query が 未完成 なら query_pending (5) で 表現
  • 必ず statuteDescription を 埋める (= #406 / datalog-debug-skill 参照)
  • userDescription (= 一覧 UI の「業務向け詳細」) は 検証主旨 (what) を業務語で書く投入手順 (「明細 を 2 行 登録 します…」) は 書かない (= 投入 データ は 子 TestRecord の label/userDescription 側)。 pyramidLevel で 書き分け: unit / integrationwhat のみ (例: 「勘定科目 が 紐付いて いない 仕訳明細 を 検出 できる こと」)、 scenariowhy (業務リスク・背景) + what (例: 「課税仕入 の 付け間違い は 利益 と 消費税額 を 歪める ため、 収入取引 に 紛れた 課税仕入明細 を 検出 できる こと」)。

Phase 2 の 詳細

  • hit 対象 row (= expectedKind=truePositive or trueNegative): label + userDescription 必須
  • 関連背景 row (= expectedKind=outOfScope): label + userDescription 任意 (= 文脈確立 用 entity、 例: 「親 deal の partner」 「同 deal 内 の 別 明細」)
  • datoms は この phase で 入れても 入れなくても OK。 入れない 場合は runStatus = test_design_pending 維持

Phase 3 の 詳細

  • datoms を 詰めて 走らせる (= datalog_testrecord_run)

  • 業務期待値 (businessExpectation) を 並走して 入れる。 #574 で 3 値文字列 (issue / no_issue / needs_review) を 廃止 し、 int ordinal の 階層 enum に 変更:

    ordinal name label 誰が 入れる
    0 no_issue_draft 正常判定 (LLMドラフト) MCP (= LLM)
    10 issue_draft 違反検知 (LLMドラフト) MCP (= LLM)
    20 no_issue 正常判定 GUI user / seed
    30 issue 違反検知 GUI user / seed
    • 権限境界 (#574): GUI user = 確定 (20 / 30) のみ / MCP (= LLM 経由 tool call) = draft (0 / 10) のみ / seed = 確定 stamp (= 業務上 issue → issue (30) / no_issue → no_issue (20))。 MCP boundary は draft 以外 を throw (assertMcpWritableBusinessExpectation) する ので、 LLM が datalog_testrecord_propose 等 で 入れる 値 は 必ず draft ordinal (0 or 10)。 user が GUI で 確定 (20 / 30) に 昇格 する。
    • draft ↔ 確定 は ordinal の 大小 (= draft < 確定) で 表現。 「LLM が 下書き → user が 確定」 という 育成 経路 を 1 enum で 持つ。
  • 解離検知: `expectedKind` ↔ `businessExpectation` が 矛盾 (= 「datalog 拾わない / 業務 issue 系」 or 「datalog 拾う / 業務 no_issue 系」) なら audit query の 限界 を 認知。 businessExpectedReason で 根拠 を 書き、 reviewEscalation'llm' (= LLM 上位 review) or 'expert' (= 専門家 review) に 設定

  • 解離 は bug でなく 正常 経路 (= 「audit は 安価 自動、 解離 case を 上位 高価 調査 に 流す」 戦略)

Phase 4 の 詳細

  • TestRecordV2.freeeKind / freeeApiPath / freeeReqBody を 詰める
  • datalog_testrecord_run で freee 投入 を 実行
  • 実走行 で resultKind 観測 → 期待 と 一致 なら runStatus = e2e_passing

kind='mixed' の 扱い

1 TestCase 内 で hit row + non-hit row が 混在 する 場合 (= 同 deal の 3 明細 で 2 件 hit / 1 件 non-hit 等)、 TestCase.kind = 'mixed' を 使う:

  • 各 TestRecordV2 で expectedKind を 個別 設定
  • TestCase 全体 で 「2 件 TP + 1 件 TN + 1 件 outOfScope (= 親 deal の partner)」 等 の 構成
  • mixed の test は multiEntity tag と 親和性 が 高い

業務期待値 と datalog 期待 の 解離 case (= 重要)

例 1: 解離 → expert review

// 同 取引、 法定外労働 = 2700 分 (= 45h ぴったり) で 「拾うべきでない」 (= datalog)
// しかし 業務上 は 「同一従業員 が 2 ヶ月 連続 45h ぴったり → 健康福祉 確保 対象」 (= 業務 issue)
{
  expectedKind: 'trueNegative',           // datalog 上 は 拾わない
  businessExpectation: 10,                // issue_draft (= 違反検知 LLMドラフト)。 LLM は draft ordinal のみ。 user が GUI で 30 (issue 確定) に 昇格
  businessExpectedReason: '2 ヶ月 連続 45h ぴったり は 健康福祉 確保 措置 対象 (= 80h 検知 ルール の 範囲外)',
  reviewEscalation: 'expert',             // 産業医 / 人事 部 へ
}

→ audit query は 「45h+1min から 拾う」 の 1 軸 だけ、 「連続 月数」 軸 は 別 query で 補う 必要。 解離 を 明示 すれば 「次の audit 設計」 ヒント に なる。

例 2: 解離 → llm review

// 課税仕入 + 取引先 紐付け 無し → 拾う (= datalog)
// しかし 業務上 「現金取引 で 3 万円 未満 だから 業務 issue でない」 (= 経過措置)
{
  expectedKind: 'truePositive',           // datalog 上 は 拾う
  businessExpectation: 0,                 // no_issue_draft (= 正常判定 LLMドラフト)。 LLM は draft ordinal のみ。 user が GUI で 20 (no_issue 確定) に 昇格
  businessExpectedReason: '現金 取引 + 3 万円 未満 (= 帳簿要件 緩和)',
  reviewEscalation: 'llm',                // LLM が 上位 ルール で 仕分け
}

→ audit query は 「課税仕入 + 取引先 無し」 で 一律 拾う、 「現金 + 3 万円 未満」 例外 は 別 query (= 緩和ルール) で 否定。


10. testRecords[] は dataSource='freee_e2e' のみ 必須 (= #436 / #535)

testRecords[] (= freee に 投入 すべき record の 集合) は 親 TestCase の dataSource 次第:

  • dataSource='freee_e2e': testRecords[] を 必ず 並べる (= freee 実投入 → e2e 走行 が 完成形)。
  • dataSource='datom_only': testRecords[] は 不要 (= freee に 作れ ない ゆえ datom 単体 で 完結。 §0 の e2eBlockedReason を 明示し、 passing が terminal green)。

旧来 の 「常時 必須 (#436)」 は #535 で freee_e2e 限定 に 改められた (= 純論理 IDB rule test 等 は datom_only で testRecords ゼロ が 正)。 詳細 雛形 / 文体 規約 / recordKind 振り分け 規則 は freee-api-test-record-skill を 参照 (= 役割分担: 本 skill は 「何を test するか」、 freee-api-test-record-skill は 「freee_e2e の とき freee 投入 record を 全部 並べる」)。

  • detected = audit query が hit すべき 対象
  • context = 検知 対象 を 成立 させる 前提 データ (= 共通 マスター / 子 entity)、 漏れ ゼロ で 並べる
  • expected_miss = 拾わ ない 期待 (= 反例)
  • out_of_scope = 範囲 外

各 record の label / userDescription は freee UI 用語 限定attr/* / instance / = 等 の 内部 略記 禁止。

GUI 連携 (= 結果は必ず画面で確認できる形で返す、 #601 / #651)

audit / testcase / testrecord の結果を user に示すときは、 テキスト説明だけで完結させず対応する GUI URL リンクをセットで提示する。 MCP 出力 (*_list / *_get / audit 実行結果) に自動付与される links (#601) をそのまま使い、 種別→画面のマッピングと host 解決は logic-solver-mcp-ui-nav §3.1.1 に従う (= URL ハードコード禁止)。

関連 skill