name: datalog-debug-skill description: freee API から同期したデータ、または任意の What-if データを DataLog (オンメモリ監査エンジン) に投入し、クエリ・監査・可視化で分析するためのスキル。会計税務・労務・社内統制の整合性監査、仮想シナリオ検証、グラフ探索を行う際に使う。

DataLog Skill

freee 会計・人事労務データを「事実 (Facts) と規則 (Rules) の集合」として取り込み、クエリ・監査・インタラクティブなグラフで分析するスキル。本番 freee データへの書き込みは発生せず (オンメモリ独立環境)、多様な入り口 (API 同期 / 自由 transact / LLM 試作) を同じグラフモデルに吸収する。

初期設定 (必須・非自動)

DataLog は MCP サーバー起動時に空の状態で立ち上がる。freee API データは 明示的に datalog_sync_* を呼ばない限り 1 件も投入されない (自動同期は無い)。クエリや監査を走らせる前に、対象ドメインに応じて以下を順に実行すること。

  1. freee_auth_status で OAuth トークンが有効か確認 (期限切れなら freee_authenticate)
  2. freee_set_current_company で対象事業所を選択
  3. datalog_reset でクリーンな環境を確保 (再 sync 時は必須)
  4. 対象データを sync (会計監査なら deals/partners/account_items/tax_codes、社労士監査なら employees/work_record_summaries)
  5. datalog_visualize で取り込み結果を確認

注意点:

ツール早見表

ツール 役割
datalog_schema 現在のスキーマ情報 (固定 + 登録済み + 動的統計 + 推奨クエリ) を一括で返す
datalog_query 任意の datalog クエリを実行
datalog_reset DataLog 環境を初期化
datalog_transact 任意 datom を投入
datalog_sync_* freee API からデータ同期 (account_items / partners / tax_codes / deals / user_matchers / employees / work_record_summaries)
datalog_visualize HTML 可視化 (自動更新)
datalog_query_list / datalog_query_get / datalog_query_create / datalog_query_update / datalog_query_delete / datalog_query_run 監査クエリ CRUD + 実行 (datalog-store/query.*.json)
datalog_idb_list / datalog_idb_get / datalog_idb_create / datalog_idb_update / datalog_idb_delete IDB (Interpretation Rules) CRUD (datalog-store/idb.*.json)。事前バリア (= 違反 datom 投入ブロック) は IDB rule の violationQuery + errorMessage で実現する (= 旧 prerule API の役割を統合済)
datalog_testrecord_list / datalog_testrecord_get TestRecord (独立 test 行) の一覧 + 1 件取得。一覧は集計 (byRunStatus / bySyncStatus / byPyramidLevel / byKindRunStatus TP/TN/FP/FN / passRate) も返す
datalog_testrecord_propose LLM が新規 test を提案、または既存 test の改修案を出す (= syncStatus='llm_proposal_pending')。承認は user が datalog_testrecord_approve で行う
datalog_testrecord_approve user が LLM 提案を承認 (= userVersion ← llmRecommendation)。AI agent からは呼ばない (audit trail 維持)
datalog_testrecord_user_edit user が userVersion を直接編集 (= syncStatus='user_diverged')
datalog_testrecord_request_change user → LLM 改修指示 (= syncStatus='user_change_requested')。次の LLM ターンが userChangeRequest を pickup して datalog_testrecord_propose で改修案を返す想定
datalog_testrecord_run userVersion を真として走行 → runStatus / actualHits / lastRunAt を persist。syncStatus='llm_proposal_pending' は skip
datalog_testrecord_delete 削除

v1 (datalog_testrecord_*) と v2 (datalog_testcase_* / datalog_testrow_*) が並走 (#177)

基本ワークフロー

A. 実データ監査 (会計・税務)

freee_set_current_company → datalog_reset → datalog_sync_account_items
→ datalog_sync_partners → datalog_sync_tax_codes → datalog_sync_deals
→ datalog_sync_user_matchers (任意: 自動仕訳ロジック監査用)
→ datalog_visualize

datalog_sync_user_matchers は freee の自動登録ルール (UserMatcher) を取り込む。明細の自動仕訳ロジック (条件 / 適用 act / 適用先 account_item) を DataLog で照合できるようになり、「ルール適用結果と実 account_item の乖離」「無効化されたまま放置されたルール」等の監査が可能。

B. 人事労務データ (社労士観点)

freee_set_current_company → datalog_sync_employees
→ datalog_sync_work_record_summaries year=YYYY month=M → datalog_visualize

C. What-if 仮想データ

datalog_transact {...} → datalog_query → datalog_visualize

D. スキーマ発見 (LLM 向け)

datalog_schema (初回のみで全体像取得)
→ 興味のある概念名を特定
→ datalog_query (返された recommendedQueries を参考に)
→ 必要なら datalog_query_create で監査化 / datalog_idb_create で IDB 化

詳細リファレンス

よくある操作

運用鉄則 (厳守)

  1. local (datalog-store/<base>.local.<breaking>.json) は絶対に手編集しない
  2. common (datalog-store/<base>.<breaking>.json) のみ手編集可
  3. 監査クエリは IDB ドメイン述語を最大限活用
  4. 足りない IDB は先に作る → その後監査クエリを書く
  5. 新規 IDB / query は test 駆動
  6. description は 3 系統で書く (#396、 audit query のみ statuteDescription 必須)
  7. status 4 値ライフサイクル (= rule / query の 稼働状況)
  8. runStatus 7 値 (= test / TestRecord の 走行・段階)

breaking version とファイル名

datalog-store/ 配下の common / local 両方にバージョンタグ (<major>.<minor>、ゼロ詰め無し) が埋め込まれる:

common: <base>.<breaking>.json         例: query.0.0.json
local : <base>.local.<breaking>.json   例: query.0.0.local.json

<breaking>package.json.version の major.minor 部分に追従する。

旧 breaking 版の local ファイルは並列に残せる ( datalog_migration_checkcurrent=false で識別)。書き直し完了後に git rm で削除可。MCP CRUD ツールは現行 breaking 版にのみ書き込む。

IDB ファースト few-shot (LLM 向け)

incident #1 で観察された誤りパターンへの対策。クエリを書く前に必ず datalog_idb_list で既存 IDB を確認し、活用可能なドメイン述語があれば畳むこと。

観察された誤りパターン

  1. (is_detail_of ?det ?deal) を使わず [?det "is_belong_to" ?deal] [?det "is_a" ?c_det] [?c_det "node/name" "明細"] を毎回展開
  2. :in $ % を書かずに IDB 述語 (rule 形式) を呼ぼうとする → DataScript が Missing rules var '%' in :in で compile error (空返りではない)
  3. datalog_query (ad-hoc) で :in $ % を書きながら inputs を空にしてしまう (audit runner と挙動が違う)
  4. 既存 IDB を datalog_idb_list で事前確認しないまま手書きクエリを書く

good / bad ペア

例 A — 明細→取引のリレーション取得

bad (アトミック述語で展開、5 述語、IDB 更新時に追従漏れ):

[:find ?detail_id
 :where [?det "is_belong_to" ?deal]
        [?det "is_a" ?c_det] [?c_det "node/name" "明細"]
        [?deal "is_a" ?c_deal] [?c_deal "node/name" "取引"]
        [?det "node/id" ?detail_id]]

good (is_detail_of IDB に畳む、:in $ % 必須):

[:find ?detail_id
 :in $ %
 :where (is_detail_of ?det ?deal)
        [?det "node/id" ?detail_id]]

例 B — :in $ % 忘れ

bad (:in $ % 無しで rule 形式を呼ぶ → Missing rules var '%' in :in エラーで失敗):

[:find ?det ?deal :where (is_detail_of ?det ?deal)]

good:

[:find ?det ?deal :in $ % :where (is_detail_of ?det ?deal)]

例 C — 複数 IDB 述語の組み合わせ

[:find ?deal_id ?partner_name
 :in $ %
 :where (is_partner_of ?partner ?deal)
        (is_detail_of ?det ?deal)
        [?deal "node/id" ?deal_id]
        [?partner "node/label" ?partner_name]]

:in $ % 経路の差 (重要)

経路 inputs に渡すもの 備考
datalog_query_run (audit runner 経由) 不要 runner が datalog-store/idb.*.json 全 IDB を自動注入 (buildIdbRulesEdn() を実行時に注入)
datalog_query (ad-hoc 直接実行) inputs[0] に IDB ルール EDN 文字列 runner と別経路。[[(rule-name ?args) <body>]] 形式の string

ad-hoc datalog_query で is_detail_of を呼ぶ場合の inputs 具体例:

[
  "[[(is_detail_of ?detail ?deal) [?detail \"is_belong_to\" ?deal] [?detail \"is_a\" ?c_det] [?c_det \"node/name\" \"明細\"] [?deal \"is_a\" ?c_deal] [?c_deal \"node/name\" \"取引\"]]]"
]

(IDB の query 形式 [:find ?a ?b :where ...][(rule-name ?a ?b) ...] に変換し、複数ルールを [] でくるんだ EDN を 1 つの string として渡す。src/logic/idb/runtime.tsidbRuleToEdn / buildIdbRulesEdn 参照)

試作段階では :in $ % 無しのアトミック述語クエリで動作確認 → 安定したら datalog_idb_create + datalog_query_create で監査化、が推奨ルート。

Pre-flight チェックリスト

クエリを書く前に:

  1. datalog_idb_list で既存 IDB を確認
  2. 活用できる IDB が無ければ datalog_idb_create で先に作る
  3. IDB 述語を呼ぶときは :find 直後の :in$ % を必ず含める
  4. ad-hoc datalog_query 利用時のみ inputs にルール EDN 明示

注意事項

開発時の reconnect 最小化

原則: normal user 経路 (= MCP tool 連続呼び出し + 必要に応じた手編集) では reconnect 一切不要。reconnect が要るのは「コード変更で bin を入れ替える」開発作業時のみ。

reconnect 要否マトリクス:

変更内容 reconnect 理由
datalog_*_create/update/delete 等の MCP CRUD 不要 notifyChanged()refreshIdbRules() で in-memory cache 自動更新
datalog-store/*.json の手編集 不要 (local) / 要 (common 反映) listQueries/listIdbRules は file 毎回再読込。ただし IDB rule edn は CRUD 経由でのみ refresh されるので、手編集後は最初の CRUD or datalog_reset 等で発火する
bun run build:ui のみ (UI bundle 差分) 不要 loadBundle() は visualize 毎回 disk 読込 → 次の datalog_visualize で新 bundle 反映
bun run build 全体 (bin 再生成) MCP host が新 bin を読み直すため
新 MCP tool 追加 / Zod schema 変更 bin 再生成必須 + tool 一覧は connect 時取得

機能完了の前に必ず: 想定 user 操作 (例: create → test → list / reset → re-sync → visualize) を vitest で e2e shape のテスト にし、reconnect 無しで pass することを確認する。

statuteDescription (法文風 Markdown — audit query 必須)

audit query (= datalog_query_create / _update) で 必ず 埋める 3 つ目の description。 税理士 / 会計士 が 税法・会計基準 と 同じ 語彙・文体 で 要件を 読めるよう、 条文風 + 箇条書き の Markdown を 持つ。

書式規約 (= LLM が守る)

3 系統 description の 役割分担

field 主読者 文体 長さ目安
userDescription 一般ユーザ 1〜3 行 平易な日本語
statuteDescription 税理士 / 会計士 条文風 Markdown、 箇条書き + 留保条件 中 (= 5〜30 行)
engineerDescription エンジニア / AI / LLM datalog 句の意図、 実装上の罠 短〜中

Few-shot 例

例 1 — deal_type_tax_purchase_mismatch (= 収入取引 に 課税仕入 明細、 税区分矛盾)

**要件**: 取引 (deal) の 種類 (収支タイプ) と、 取引内に 含まれる 明細 (deal_detail) の 税区分 が 整合 すること

**判定条件**:
- 取引 (deal) が **収入** に 分類されていること
- かつ、 取引内に **税区分 が 「課税仕入」** の 明細 (deal_detail) が 1 件以上 存在すること

**該当する場合は要修正**: 収入取引に 仕入 明細 が 混在しており、 消費税集計の 性質 (= 売上 vs 仕入) が 不整合。 仕訳 が 誤って 入力されている 可能性が 高く、 消費税申告 に 影響する。

(参考: 消費税法 第30条 仕入税額控除 / 同 第28条 売上 — 性質 区分 の 厳格性)

例 2 — taxable_purchase_no_partner (= 課税仕入 なのに 取引先 未紐付け)

**要件**: 課税仕入 の 取引 について、 **取引先** の 記録 が ある こと

**判定条件**:
- 取引 (deal) が **以下のいずれか** を 満たす こと:
  - 明細 (deal_detail) のうち、 税区分 が 「課税仕入」 であるもの が 1 件以上 存在する
- かつ、 上記取引 について **次のいずれも 満たさない**:
  - 取引 (deal) 自体 に **取引先 (partner)** が 紐付いている
  - 課税仕入 の 明細 (deal_detail) 自身 に **取引先 (partner)** が 紐付いている

**該当する場合は要調査**: 取引帳簿 の 真実性要件 (= 取引先名 の 記録義務) を 満たさない 可能性 が ある。

(参考: 消費税法 第30条第7項 仕入税額控除 の 帳簿要件)

例 3 — overtime_36agreement (= 36 協定超過)

**要件**: 法定外労働時間 が 月 ≤ 45 時間 で あること (= 36 協定 の 限度時間)

**判定条件**:
- 月次勤怠 (monthly_work_record) が **法定外労働時間** を 記録 している こと
- かつ、 月次勤怠 の 法定外労働時間 が **45 時間 を 超えている** こと

**該当する場合は要修正**: 36 協定 (= 労働基準法 第36条) で 定める 限度時間 を 超過 しており、 違反 の 可能性 が ある。

(参考: 労働基準法 第36条 / 同 施行規則 第16条)

強制ルール

関連スキル