@kansei-link/bantou 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +110 -0
- package/data/exclusion-rules/README.md +104 -0
- package/data/exclusion-rules/jp-tax-baseline-v1.json +185 -0
- package/data/exclusion-rules-schema.json +109 -0
- package/data/keyword-dict/README.md +91 -0
- package/data/keyword-dict/jp-tax-baseline-v1.json +398 -0
- package/data/keyword-dict-schema.json +117 -0
- package/data/tax-rules/jp-tax-rules-v1.json +170 -0
- package/dist/adapters/csv-parser.d.ts +11 -0
- package/dist/adapters/csv-parser.js +133 -0
- package/dist/adapters/freee-csv-adapter.d.ts +14 -0
- package/dist/adapters/freee-csv-adapter.js +67 -0
- package/dist/adapters/generic-adapter.d.ts +20 -0
- package/dist/adapters/generic-adapter.js +73 -0
- package/dist/adapters/index.d.ts +23 -0
- package/dist/adapters/index.js +386 -0
- package/dist/adapters/types.d.ts +111 -0
- package/dist/adapters/types.js +9 -0
- package/dist/adapters/yayoi-adapter.d.ts +46 -0
- package/dist/adapters/yayoi-adapter.js +181 -0
- package/dist/bin/freee-doctor.d.ts +3 -0
- package/dist/bin/freee-doctor.js +15 -0
- package/dist/classifier/claude-classifier.d.ts +24 -0
- package/dist/classifier/claude-classifier.js +154 -0
- package/dist/classifier/keyword-classifier.d.ts +22 -0
- package/dist/classifier/keyword-classifier.js +124 -0
- package/dist/classifier/keyword-match.d.ts +21 -0
- package/dist/classifier/keyword-match.js +57 -0
- package/dist/classifier/normalize.d.ts +3 -0
- package/dist/classifier/normalize.js +27 -0
- package/dist/classifier/two-stage-classifier.d.ts +21 -0
- package/dist/classifier/two-stage-classifier.js +51 -0
- package/dist/classifier/types.d.ts +31 -0
- package/dist/classifier/types.js +3 -0
- package/dist/connectors/freee.d.ts +115 -0
- package/dist/connectors/freee.js +177 -0
- package/dist/exclusion/exclusion-checker.d.ts +10 -0
- package/dist/exclusion/exclusion-checker.js +162 -0
- package/dist/freee-doctor.d.ts +26 -0
- package/dist/freee-doctor.js +82 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +656 -0
- package/dist/memory/cockpit-memory.d.ts +73 -0
- package/dist/memory/cockpit-memory.js +473 -0
- package/dist/memory/types.d.ts +114 -0
- package/dist/memory/types.js +11 -0
- package/dist/pipeline/confidence-router.d.ts +38 -0
- package/dist/pipeline/confidence-router.js +129 -0
- package/dist/pipeline/nightly-pipeline.d.ts +44 -0
- package/dist/pipeline/nightly-pipeline.js +497 -0
- package/dist/pipeline/types.d.ts +84 -0
- package/dist/pipeline/types.js +12 -0
- package/dist/reports/monthly-report.d.ts +64 -0
- package/dist/reports/monthly-report.js +230 -0
- package/dist/secrets.d.ts +14 -0
- package/dist/secrets.js +86 -0
- package/dist/tax-rules/tax-rule-engine.d.ts +103 -0
- package/dist/tax-rules/tax-rule-engine.js +449 -0
- package/dist/tax-rules/types.d.ts +103 -0
- package/dist/tax-rules/types.js +7 -0
- package/package.json +74 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Synapse Arrows PTE. LTD.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# @kansei-link/cockpit
|
|
2
|
+
|
|
3
|
+
MCP (Model Context Protocol) server for Japanese tax accountant workflow automation.
|
|
4
|
+
|
|
5
|
+
税理士業務の自動化を実現する MCP サーバー。仕訳分類・消費税判定・インボイス制度チェック・CSV取込を一気通貫で処理します。
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @kansei-link/cockpit
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
Add to your `claude_desktop_config.json`:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"mcpServers": {
|
|
20
|
+
"cockpit": {
|
|
21
|
+
"command": "npx",
|
|
22
|
+
"args": ["@kansei-link/cockpit"],
|
|
23
|
+
"env": {
|
|
24
|
+
"COCKPIT_DATA_DIR": "/path/to/data"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Key Features
|
|
32
|
+
|
|
33
|
+
- **Two-stage classifier** -- Stage 1: keyword matching across 19 categories with 500+ keywords; Stage 2: Claude AI fallback for ambiguous entries
|
|
34
|
+
- **TaxRuleEngine** -- Consumption tax with 8%/10% reduced rate logic, overseas SaaS and ad platform detection, withholding tax calculation, asset tier classification, and invoice system (インボイス制度) checker with transitional period handling
|
|
35
|
+
- **CSV adapters** -- Auto-detect and parse Yayoi (弥生), freee, and generic CSV formats
|
|
36
|
+
- **Persistent memory** -- Linksee Memory integration that learns from corrections and recalls learned patterns
|
|
37
|
+
- **Confidence routing** -- Automatic routing to `auto_register`, `auto_register_with_log`, or `human_review` based on confidence scores and business rules
|
|
38
|
+
- **200 tests** -- Comprehensive test suite including end-to-end integration tests
|
|
39
|
+
|
|
40
|
+
## Architecture
|
|
41
|
+
|
|
42
|
+
The classification pipeline processes each transaction through sequential stages:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
CSV Input
|
|
46
|
+
|
|
|
47
|
+
v
|
|
48
|
+
[CSV Adapter] -- Auto-detect format (Yayoi / freee / generic)
|
|
49
|
+
|
|
|
50
|
+
v
|
|
51
|
+
[Normalizer] -- Text normalization, full-width/half-width conversion
|
|
52
|
+
|
|
|
53
|
+
v
|
|
54
|
+
[Stage 1: Keyword Classifier] -- 19 categories, 500+ keyword rules
|
|
55
|
+
| (high confidence) | (low confidence)
|
|
56
|
+
v v
|
|
57
|
+
[TaxRuleEngine] [Stage 2: Claude AI Classifier]
|
|
58
|
+
| |
|
|
59
|
+
v v
|
|
60
|
+
[TaxRuleEngine] [TaxRuleEngine]
|
|
61
|
+
| |
|
|
62
|
+
v v
|
|
63
|
+
[Confidence Router] -- auto_register / auto_register_with_log / human_review
|
|
64
|
+
|
|
|
65
|
+
v
|
|
66
|
+
[Memory Store] -- Persist corrections, recall patterns (Linksee Memory)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### TaxRuleEngine Details
|
|
70
|
+
|
|
71
|
+
- **Consumption tax**: Standard 10%, reduced rate 8% (food/beverages, newspapers)
|
|
72
|
+
- **Overseas detection**: SaaS platforms (AWS, Azure, GCP, etc.), advertising (Google Ads, Meta Ads, etc.) -- reverse charge applicable
|
|
73
|
+
- **Withholding tax**: Professional fees, royalties, and other specified payments
|
|
74
|
+
- **Asset classification**: Expense / depreciable asset / lump-sum depreciable asset / small-value asset based on acquisition cost tiers
|
|
75
|
+
- **Invoice checker**: Registration number validation, transitional credit periods (2023-10 through 2029-09)
|
|
76
|
+
|
|
77
|
+
## Configuration
|
|
78
|
+
|
|
79
|
+
### Environment Variables
|
|
80
|
+
|
|
81
|
+
| Variable | Description | Default |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| `COCKPIT_DATA_DIR` | Path to data directory containing keyword dictionaries and tax rules | `./data` |
|
|
84
|
+
|
|
85
|
+
### Data Files
|
|
86
|
+
|
|
87
|
+
The `data/` directory contains:
|
|
88
|
+
|
|
89
|
+
- `keyword-dict/jp-tax-baseline-v1.json` -- Keyword dictionary for Stage 1 classification (19 categories, 500+ rules)
|
|
90
|
+
- `tax-rules/jp-tax-rules-v1.json` -- Consumption tax rates, overseas SaaS/ad platforms, withholding rules, asset tiers, invoice system config
|
|
91
|
+
- `exclusion-rules/jp-tax-baseline-v1.json` -- Patterns to exclude non-classifiable transactions (ATM, salary, transfers, etc.)
|
|
92
|
+
|
|
93
|
+
## Development
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Run in development mode
|
|
97
|
+
npm run dev
|
|
98
|
+
|
|
99
|
+
# Run tests
|
|
100
|
+
npm test
|
|
101
|
+
|
|
102
|
+
# Build
|
|
103
|
+
npm run build
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## License
|
|
107
|
+
|
|
108
|
+
MIT -- see [LICENSE](./LICENSE) for details.
|
|
109
|
+
|
|
110
|
+
Copyright (c) 2026 Synapse Arrows PTE. LTD.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Cockpit MCP — Exclusion Rules
|
|
2
|
+
|
|
3
|
+
## What this is
|
|
4
|
+
|
|
5
|
+
Cockpit MCP's **Stage 0 filter** runs BEFORE the keyword/AI classifier. It identifies transactions that should NOT be auto-journalized — they get escalated to human review instead.
|
|
6
|
+
|
|
7
|
+
This is the **practitioner-style 7-rule exclusion** pattern. From the reference note:
|
|
8
|
+
|
|
9
|
+
> 自動仕訳で一番怖いのは「本来仕訳すべきでないものを仕訳してしまう」ことです。
|
|
10
|
+
> 「何を自動化して、何を人間が見るか」の線引きを明確にしているからこそ、安全に60社を回せています。
|
|
11
|
+
|
|
12
|
+
The 7 rules:
|
|
13
|
+
|
|
14
|
+
1. **内容不明デビット** — "デビット+数字" だけで店名なし → 人間が利用明細確認
|
|
15
|
+
2. **借入金返済** — 元本+利息 内訳必要 → freee 借入金返済 wizard 推奨
|
|
16
|
+
3. **社会保険料・税金** — 法定福利費 / 預り金 / 租税公課 判断必要
|
|
17
|
+
4. **給与支払い** — 給与計算結果と連動必要 → freee 人事労務 wizard
|
|
18
|
+
5. **投資・資産運用** — 投資有価証券 / 雑所得 / 譲渡益 判断、 税理士判断
|
|
19
|
+
6. **ATM出金・残高調整** — 口座振替別処理、 cash_balance_adjustment workflow へ
|
|
20
|
+
7. **公共料金** — 事業 vs 個人按分必要 → 手動比率設定
|
|
21
|
+
|
|
22
|
+
## How matching works
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
Transaction (= memo, amount, date, partner_name)
|
|
26
|
+
↓
|
|
27
|
+
Stage 0 (Exclusion Rules)
|
|
28
|
+
├─ Rule 1 match? → human_review (rule_id, reason)
|
|
29
|
+
├─ Rule 2 match? → human_review
|
|
30
|
+
├─ ...
|
|
31
|
+
└─ No match → proceed to Stage 1
|
|
32
|
+
↓
|
|
33
|
+
Stage 1 (Keyword Dict)
|
|
34
|
+
├─ Match? → return classification
|
|
35
|
+
└─ No match → Stage 2
|
|
36
|
+
↓
|
|
37
|
+
Stage 2 (Claude API fallback)
|
|
38
|
+
→ return with confidence (high/medium/low)
|
|
39
|
+
→ low confidence → human review
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Action types
|
|
43
|
+
|
|
44
|
+
- **human_review**: Transaction goes to "確認待ち" queue. Tax accountant reviews + manually classifies.
|
|
45
|
+
- **alternative_workflow**: Transaction is routed to a different workflow (e.g., ATM withdrawal → cash_balance_adjustment, NOT auto-journalized but auto-handled).
|
|
46
|
+
- **skip_silently**: Transaction is ignored entirely (= for noise filtering, rare use).
|
|
47
|
+
|
|
48
|
+
## Per-firm overrides
|
|
49
|
+
|
|
50
|
+
Each Cockpit user (= 税理士事務所) can define overrides:
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"firm_id": "tanaka-tax-office",
|
|
55
|
+
"rule_overrides": [
|
|
56
|
+
{
|
|
57
|
+
"rule_id": "investment",
|
|
58
|
+
"additional_keywords": ["弊社専用ファンド名"],
|
|
59
|
+
"exclude_keywords": ["NISA"]
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"rule_id": "salary_payment",
|
|
63
|
+
"disabled": true,
|
|
64
|
+
"reason": "うちの事務所は freee HR 連動完成済"
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
→ Stored in Cockpit Web Dashboard, applied per-instance via Cockpit MCP.
|
|
71
|
+
|
|
72
|
+
## Validation
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# Schema validation (TODO: add to CI)
|
|
76
|
+
node scripts/validate-exclusion-rules.js data/exclusion-rules/*.json
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Smoke test scenarios
|
|
80
|
+
|
|
81
|
+
`packages/cockpit-mcp/tests/exclusion-rules.test.ts` covers:
|
|
82
|
+
|
|
83
|
+
1. "デビット 12345" → unknown_debit, human_review
|
|
84
|
+
2. "公庫 利息支払い" → loan_repayment
|
|
85
|
+
3. "源泉所得税納付" → social_insurance_tax
|
|
86
|
+
4. "給与 山田太郎" + freee HR list 含む → salary_payment
|
|
87
|
+
5. "野村證券 譲渡代金" → investment
|
|
88
|
+
6. "セブン銀行ATM出金" → atm_withdrawal → cash_balance_adjustment workflow
|
|
89
|
+
7. "東京水道局" → utilities (公共料金)
|
|
90
|
+
8. "Suica チャージ" → no match → proceed to Stage 1 (= 旅費交通費 にいく)
|
|
91
|
+
|
|
92
|
+
## Partnership note
|
|
93
|
+
|
|
94
|
+
These 7 rules are the canonical practitioner playbook. Year 1 closed beta:
|
|
95
|
+
- Tax practitioner reviews + signs off (= 「これが私の 7 rule で間違いない」)
|
|
96
|
+
- Co-author credit in `maintainer` field
|
|
97
|
+
- His extensions (= 8th, 9th rule) merged via PR
|
|
98
|
+
|
|
99
|
+
## See also
|
|
100
|
+
|
|
101
|
+
- Schema: [`../exclusion-rules-schema.json`](../exclusion-rules-schema.json)
|
|
102
|
+
- Architecture: [`../../docs/architecture.md`](../../docs/architecture.md)
|
|
103
|
+
- keyword-dict (Stage 1): [`../keyword-dict/README.md`](../keyword-dict/README.md)
|
|
104
|
+
- Strategy: [synapse-arrows-playbook Doc 10](https://github.com/michielinksee/synapse-arrows-playbook/blob/main/04-tooling-gaps/10-kansei-link-cockpit-strategy.md)
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../exclusion-rules-schema.json",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"locale": "ja-JP",
|
|
5
|
+
"tax_jurisdiction": "JP",
|
|
6
|
+
"last_updated": "2026-05-09",
|
|
7
|
+
"maintainer": "Synapse Arrows PTE. LTD.",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"description": "Cockpit MCP の Stage 0 exclusion filter。 自動仕訳すべきでない transaction を弾いて 人間 review に escalate する。 実務ベースの 7 種除外ルール。",
|
|
10
|
+
"notes": [
|
|
11
|
+
"execution: classify_transaction の前に check_exclusion を必ず call",
|
|
12
|
+
"match → return { excluded: true, rule_id, reason, action: 'human_review' }",
|
|
13
|
+
"no match → classify_transaction (Stage 1+2) へ進む",
|
|
14
|
+
"rule priority: 上から順 (= 同 transaction が複数 rule match なら 上のが採用)",
|
|
15
|
+
"extension: 各事務所が override / 追加可能 (= per-firm exclusion overrides 機構)"
|
|
16
|
+
],
|
|
17
|
+
"rules": [
|
|
18
|
+
{
|
|
19
|
+
"id": "unknown_debit",
|
|
20
|
+
"name_ja": "内容不明デビット",
|
|
21
|
+
"name_en": "Unknown debit (no merchant name)",
|
|
22
|
+
"description": "「デビット+数字」だけで店名がない transaction。 詳細不明のため自動仕訳せず人間 review。",
|
|
23
|
+
"priority": 1,
|
|
24
|
+
"match": {
|
|
25
|
+
"type": "regex",
|
|
26
|
+
"field": "memo",
|
|
27
|
+
"pattern": "^デビット[\\s\\d\\-]*$",
|
|
28
|
+
"flags": "i"
|
|
29
|
+
},
|
|
30
|
+
"alternative_patterns": [
|
|
31
|
+
"デビット利用",
|
|
32
|
+
"DEBIT",
|
|
33
|
+
"VISA DEBIT 振替"
|
|
34
|
+
],
|
|
35
|
+
"action": {
|
|
36
|
+
"type": "human_review",
|
|
37
|
+
"reason_template": "店名不明のデビット取引。 通帳 or 利用明細から店名特定後 人間判断 required。",
|
|
38
|
+
"suggested_next_step": "freee 上で取引詳細を開き、 利用明細から merchant 確定 → 適切な category へ分類"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"id": "loan_repayment",
|
|
43
|
+
"name_ja": "借入金返済",
|
|
44
|
+
"name_en": "Loan repayment",
|
|
45
|
+
"description": "公庫・銀行借入 / ローン返済。 元本+利息 内訳 が必要なため自動仕訳せず。",
|
|
46
|
+
"priority": 2,
|
|
47
|
+
"match": {
|
|
48
|
+
"type": "any_keyword",
|
|
49
|
+
"field": "memo",
|
|
50
|
+
"keywords": [
|
|
51
|
+
"公庫", "日本政策金融公庫", "JFC",
|
|
52
|
+
"融資", "借入", "借入金返済", "返済",
|
|
53
|
+
"ローン", "Loan", "LOAN",
|
|
54
|
+
"信金", "信用金庫",
|
|
55
|
+
"商工中金",
|
|
56
|
+
"プロパー融資"
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
"action": {
|
|
60
|
+
"type": "human_review",
|
|
61
|
+
"reason_template": "借入金返済または融資関連取引。 元本 / 利息 内訳必要、 freee の 借入金返済 wizard 推奨。",
|
|
62
|
+
"suggested_next_step": "freee → 取引 → 借入金返済 wizard で元本・利息分離"
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"id": "social_insurance_tax",
|
|
67
|
+
"name_ja": "社会保険料・税金",
|
|
68
|
+
"name_en": "Social insurance & taxes",
|
|
69
|
+
"description": "年金 / 健保 / 源泉所得税 / 住民税 / 法人税 等の納付。 仕訳科目が複雑なため自動 NG。",
|
|
70
|
+
"priority": 3,
|
|
71
|
+
"match": {
|
|
72
|
+
"type": "any_keyword",
|
|
73
|
+
"field": "memo",
|
|
74
|
+
"keywords": [
|
|
75
|
+
"年金", "厚生年金", "国民年金",
|
|
76
|
+
"健保", "健康保険", "協会けんぽ", "けんぽ",
|
|
77
|
+
"源泉", "源泉税", "源泉所得税",
|
|
78
|
+
"住民税", "市民税", "県民税", "都民税",
|
|
79
|
+
"法人税", "事業税", "消費税納付",
|
|
80
|
+
"労災", "雇用保険",
|
|
81
|
+
"国税", "地方税",
|
|
82
|
+
"印紙税"
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
"action": {
|
|
86
|
+
"type": "human_review",
|
|
87
|
+
"reason_template": "社保・税金納付。 法定福利費 / 預り金 / 租税公課 等の科目選択判断必要。",
|
|
88
|
+
"suggested_next_step": "freee → 取引 → 社会保険料 / 税金 wizard で適切科目選択"
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"id": "salary_payment",
|
|
93
|
+
"name_ja": "給与支払い",
|
|
94
|
+
"name_en": "Salary payment",
|
|
95
|
+
"description": "従業員への給与振込。 freee 人事労務 API から従業員名 list を取得して match。 自動仕訳禁止 (= 給与計算と連動の必要)。",
|
|
96
|
+
"priority": 4,
|
|
97
|
+
"match": {
|
|
98
|
+
"type": "any_keyword_or_pattern",
|
|
99
|
+
"field": "memo",
|
|
100
|
+
"keywords": [
|
|
101
|
+
"給与", "給料", "ボーナス", "賞与"
|
|
102
|
+
],
|
|
103
|
+
"patterns": [
|
|
104
|
+
{
|
|
105
|
+
"type": "transfer_to_employee",
|
|
106
|
+
"description": "振込 + freee 人事労務 API の従業員 list 内の名前 match",
|
|
107
|
+
"requires_external_data": "freee_hr_employee_list"
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
},
|
|
111
|
+
"action": {
|
|
112
|
+
"type": "human_review",
|
|
113
|
+
"reason_template": "給与振込検出。 給与計算結果と整合確認後、 freee 給与仕訳 wizard で起票。",
|
|
114
|
+
"suggested_next_step": "freee 人事労務 → 給与計算 → 仕訳作成 で自動連動"
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"id": "investment",
|
|
119
|
+
"name_ja": "投資・資産運用",
|
|
120
|
+
"name_en": "Investment / securities",
|
|
121
|
+
"description": "証券口座への入出金、 投資信託 等。 投資勘定 / 雑所得 / 譲渡益 等の判断必要。",
|
|
122
|
+
"priority": 5,
|
|
123
|
+
"match": {
|
|
124
|
+
"type": "any_keyword",
|
|
125
|
+
"field": "memo",
|
|
126
|
+
"keywords": [
|
|
127
|
+
"証券", "野村", "大和", "SMBC日興", "みずほ証券", "三菱UFJモルガン",
|
|
128
|
+
"SBI証券", "楽天証券", "マネックス", "auカブコム", "松井証券",
|
|
129
|
+
"投資信託", "ファンド", "FUND",
|
|
130
|
+
"株式", "株",
|
|
131
|
+
"FX", "暗号資産", "Bitflyer", "Coincheck", "GMOコイン",
|
|
132
|
+
"REIT", "ETF",
|
|
133
|
+
"NISA", "iDeCo", "つみたて"
|
|
134
|
+
]
|
|
135
|
+
},
|
|
136
|
+
"action": {
|
|
137
|
+
"type": "human_review",
|
|
138
|
+
"reason_template": "投資・資産運用関連取引。 仕訳科目 (= 投資有価証券 / 雑所得 / 譲渡益等) は税理士判断。",
|
|
139
|
+
"suggested_next_step": "個別 review、 必要なら年度末まで仮勘定で保持"
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"id": "atm_withdrawal",
|
|
144
|
+
"name_ja": "ATM出金・残高調整",
|
|
145
|
+
"name_en": "ATM withdrawal / balance adjustment",
|
|
146
|
+
"description": "ATM 出金は口座振替で別処理。 仕訳起票せず、 別途 balance adjustment workflow へ。",
|
|
147
|
+
"priority": 6,
|
|
148
|
+
"match": {
|
|
149
|
+
"type": "any_keyword",
|
|
150
|
+
"field": "memo",
|
|
151
|
+
"keywords": [
|
|
152
|
+
"ATM", "ATM出金", "現金引出", "引出", "引き出し",
|
|
153
|
+
"ゆうちょATM", "コンビニATM",
|
|
154
|
+
"セブン銀行ATM", "イオン銀行ATM"
|
|
155
|
+
]
|
|
156
|
+
},
|
|
157
|
+
"action": {
|
|
158
|
+
"type": "alternative_workflow",
|
|
159
|
+
"alternative_workflow_id": "cash_balance_adjustment",
|
|
160
|
+
"reason_template": "ATM 出金 / 現金引出。 口座振替として別処理、 現金勘定残高調整に流す。",
|
|
161
|
+
"suggested_next_step": "freee → 振替伝票 → 普通預金 → 現金"
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"id": "utilities",
|
|
166
|
+
"name_ja": "公共料金",
|
|
167
|
+
"name_en": "Public utilities (no matching account category)",
|
|
168
|
+
"description": "個人宅の電気・ガス・水道。 事業所契約と区別困難なため、 自動 NG。 (事業所契約の utilities は keyword-dict utilities category で別途処理)",
|
|
169
|
+
"priority": 7,
|
|
170
|
+
"match": {
|
|
171
|
+
"type": "any_keyword",
|
|
172
|
+
"field": "memo",
|
|
173
|
+
"keywords": [
|
|
174
|
+
"東京水道局", "東京都水道", "水道局", "上下水道",
|
|
175
|
+
"NHK受信料", "NHK"
|
|
176
|
+
]
|
|
177
|
+
},
|
|
178
|
+
"action": {
|
|
179
|
+
"type": "human_review",
|
|
180
|
+
"reason_template": "公共料金検出。 事業利用 vs 個人利用の按分判断必要。",
|
|
181
|
+
"suggested_next_step": "事業利用比率 (= 例: 自宅事務所なら 30%) を手動設定後仕訳"
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
]
|
|
185
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://github.com/michielinksee/kansei-link-cockpit/blob/main/data/exclusion-rules-schema.json",
|
|
4
|
+
"title": "Cockpit MCP Exclusion Rules",
|
|
5
|
+
"description": "Schema for Stage 0 exclusion filters used by Cockpit MCP. These run BEFORE classify_transaction. Matching transactions are escalated to human review (= NOT auto-journalized).",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["version", "locale", "tax_jurisdiction", "rules"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" },
|
|
10
|
+
"locale": { "type": "string", "pattern": "^[a-z]{2}-[A-Z]{2}$" },
|
|
11
|
+
"tax_jurisdiction": { "type": "string", "pattern": "^[A-Z]{2}$" },
|
|
12
|
+
"last_updated": { "type": "string", "format": "date" },
|
|
13
|
+
"maintainer": { "type": "string" },
|
|
14
|
+
"license": { "type": "string" },
|
|
15
|
+
"description": { "type": "string" },
|
|
16
|
+
"notes": {
|
|
17
|
+
"type": "array",
|
|
18
|
+
"items": { "type": "string" }
|
|
19
|
+
},
|
|
20
|
+
"rules": {
|
|
21
|
+
"type": "array",
|
|
22
|
+
"minItems": 1,
|
|
23
|
+
"items": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"required": ["id", "name_ja", "description", "priority", "match", "action"],
|
|
26
|
+
"properties": {
|
|
27
|
+
"id": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"pattern": "^[a-z_]+$"
|
|
30
|
+
},
|
|
31
|
+
"name_ja": { "type": "string" },
|
|
32
|
+
"name_en": { "type": "string" },
|
|
33
|
+
"description": { "type": "string" },
|
|
34
|
+
"priority": {
|
|
35
|
+
"type": "integer",
|
|
36
|
+
"description": "Lower = higher priority. Rules evaluated top to bottom; first match wins."
|
|
37
|
+
},
|
|
38
|
+
"match": {
|
|
39
|
+
"type": "object",
|
|
40
|
+
"required": ["type", "field"],
|
|
41
|
+
"properties": {
|
|
42
|
+
"type": {
|
|
43
|
+
"type": "string",
|
|
44
|
+
"enum": ["regex", "any_keyword", "any_keyword_or_pattern", "exact"]
|
|
45
|
+
},
|
|
46
|
+
"field": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"enum": ["memo", "amount", "partner_name", "date"],
|
|
49
|
+
"description": "Which transaction field to match against (after normalization)"
|
|
50
|
+
},
|
|
51
|
+
"pattern": {
|
|
52
|
+
"type": "string",
|
|
53
|
+
"description": "Regex pattern (when type=regex)"
|
|
54
|
+
},
|
|
55
|
+
"flags": {
|
|
56
|
+
"type": "string",
|
|
57
|
+
"description": "Regex flags like 'i', 'g' (when type=regex)"
|
|
58
|
+
},
|
|
59
|
+
"keywords": {
|
|
60
|
+
"type": "array",
|
|
61
|
+
"items": { "type": "string" },
|
|
62
|
+
"description": "Substring list (when type=any_keyword or any_keyword_or_pattern)"
|
|
63
|
+
},
|
|
64
|
+
"patterns": {
|
|
65
|
+
"type": "array",
|
|
66
|
+
"items": {
|
|
67
|
+
"type": "object",
|
|
68
|
+
"properties": {
|
|
69
|
+
"type": { "type": "string" },
|
|
70
|
+
"description": { "type": "string" },
|
|
71
|
+
"requires_external_data": { "type": "string" }
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"description": "Custom pattern detectors (e.g., transfer_to_employee requires freee_hr_employee_list)"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"alternative_patterns": {
|
|
79
|
+
"type": "array",
|
|
80
|
+
"items": { "type": "string" },
|
|
81
|
+
"description": "Additional substring fallbacks beyond the primary match"
|
|
82
|
+
},
|
|
83
|
+
"action": {
|
|
84
|
+
"type": "object",
|
|
85
|
+
"required": ["type", "reason_template"],
|
|
86
|
+
"properties": {
|
|
87
|
+
"type": {
|
|
88
|
+
"type": "string",
|
|
89
|
+
"enum": ["human_review", "alternative_workflow", "skip_silently"]
|
|
90
|
+
},
|
|
91
|
+
"reason_template": {
|
|
92
|
+
"type": "string",
|
|
93
|
+
"description": "Human-readable reason shown to the tax accountant"
|
|
94
|
+
},
|
|
95
|
+
"suggested_next_step": {
|
|
96
|
+
"type": "string",
|
|
97
|
+
"description": "Concrete recommendation for the human reviewer"
|
|
98
|
+
},
|
|
99
|
+
"alternative_workflow_id": {
|
|
100
|
+
"type": "string",
|
|
101
|
+
"description": "If type=alternative_workflow, ID of the workflow to invoke (e.g., cash_balance_adjustment)"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Cockpit MCP — Keyword Dictionary
|
|
2
|
+
|
|
3
|
+
## What this is
|
|
4
|
+
|
|
5
|
+
Cockpit MCP's **Stage 1 classifier** uses keyword dictionaries to map raw transaction 摘要 (= memo strings) to 勘定科目 (= account categories) + 税区分 (= tax codes).
|
|
6
|
+
|
|
7
|
+
This is the **practitioner-style 14 categories × 100 keywords** approach, packaged as portable JSON for free distribution. Each tax jurisdiction has its own dictionary file:
|
|
8
|
+
|
|
9
|
+
- `jp-tax-baseline-v1.json` — Japanese tax accounting baseline (14 categories)
|
|
10
|
+
- (future) `sg-tax-baseline-v1.json` — Singapore GST + ACRA-aligned categories
|
|
11
|
+
- (future) `us-tax-baseline-v1.json` — US sales tax + GAAP categories
|
|
12
|
+
|
|
13
|
+
## How matching works
|
|
14
|
+
|
|
15
|
+
1. **Normalize** 摘要 string: 全角 → 半角、 大文字 → 小文字、 trim whitespace
|
|
16
|
+
2. **Iterate categories** (top to bottom) and for each, check if any keyword is a substring of the normalized 摘要
|
|
17
|
+
3. **First match wins**: if "Suica" matches in `travel`, classifier returns `travel`. No further categories checked.
|
|
18
|
+
4. **Apply amount thresholds** (if defined): e.g., 会議費 only matches ≤¥10K; if amount > ¥10K, auto-redirect to 交際費 via `amount_overflow_category`
|
|
19
|
+
5. **Apply special patterns** (if defined): e.g., `transfer_professional` requires the keyword AND a 振込 verb in the 摘要
|
|
20
|
+
6. If no category matches → fallback to **Stage 2** (Claude API classifier with confidence high/medium/low)
|
|
21
|
+
|
|
22
|
+
## Versioning
|
|
23
|
+
|
|
24
|
+
- `v1.0.0` = initial baseline (= 14 categories × ~50 keywords average)
|
|
25
|
+
- `v1.x` = expand to 100 keywords/category via dogfood iterations
|
|
26
|
+
- `v2.x` = community-tuned (= Cockpit user 集合知 で keyword 改善)
|
|
27
|
+
- `v3.x` = AI-discovered keywords (= 過去 anonymous data から AI が新 keyword 発見)
|
|
28
|
+
|
|
29
|
+
## How to extend
|
|
30
|
+
|
|
31
|
+
### Add new keyword to existing category
|
|
32
|
+
|
|
33
|
+
1. Open the relevant `*-tax-baseline-v*.json`
|
|
34
|
+
2. Find the category by `id`
|
|
35
|
+
3. Append your keyword to the `keywords` array
|
|
36
|
+
4. Test: run smoke test against your test fixtures
|
|
37
|
+
5. Open PR (= reviewer must verify keyword is unambiguous + likely to match real transactions)
|
|
38
|
+
|
|
39
|
+
### Add new category
|
|
40
|
+
|
|
41
|
+
1. Define new entry in `categories` array with all required fields (= `id`, `name_ja`, `freee_account_code`, `default_tax_code`, `keywords`)
|
|
42
|
+
2. Choose `freee_account_code` from freee's standard chart of accounts
|
|
43
|
+
3. Determine `default_tax_code` based on Japanese 消費税 rules
|
|
44
|
+
4. Decide priority (= where in the categories array it goes — earlier = higher priority)
|
|
45
|
+
5. Add at least 10 initial keywords to bootstrap
|
|
46
|
+
6. Run smoke test
|
|
47
|
+
7. Open PR (= reviewer verifies category is genuinely needed and not a duplicate)
|
|
48
|
+
|
|
49
|
+
### Add jurisdiction-specific dictionary
|
|
50
|
+
|
|
51
|
+
1. Copy `jp-tax-baseline-v1.json` → `<country-code>-tax-baseline-v1.json`
|
|
52
|
+
2. Update `locale` and `tax_jurisdiction` fields
|
|
53
|
+
3. Replace categories with the target country's chart of accounts
|
|
54
|
+
4. Provide a community maintainer (= regional accountant) to validate
|
|
55
|
+
5. Open PR
|
|
56
|
+
|
|
57
|
+
## Partnership note
|
|
58
|
+
|
|
59
|
+
This dictionary is designed to be **co-authored with tax practitioners** starting Year 1 closed beta:
|
|
60
|
+
|
|
61
|
+
- Practitioner's 6-month-built 14 categories × 100 keywords → contributed as anonymous PR
|
|
62
|
+
- Co-author credit in `maintainer` field
|
|
63
|
+
- Quarterly merge of practitioner improvements + community improvements
|
|
64
|
+
- See `synapse-arrows-playbook/04-tooling-gaps/10-kansei-link-cockpit-strategy.md` §11 for partnership terms
|
|
65
|
+
|
|
66
|
+
## Validation
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Run schema validation (TODO: add to CI)
|
|
70
|
+
node scripts/validate-keyword-dict.js data/keyword-dict/*.json
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Smoke test scenarios
|
|
74
|
+
|
|
75
|
+
`packages/cockpit-mcp/tests/keyword-dict.test.ts` covers:
|
|
76
|
+
|
|
77
|
+
1. Basic substring match (= "Suica" → travel)
|
|
78
|
+
2. Multi-keyword match (= 上 category 優先)
|
|
79
|
+
3. Amount threshold (= "スターバックス @ ¥15,000" → entertainment, NOT meeting_meal)
|
|
80
|
+
4. Special pattern: salary employee detection (= 給与 + 従業員名 list match)
|
|
81
|
+
5. Special pattern: 振込 + 士業名 → professional_fee + 取引先抽出
|
|
82
|
+
6. Special pattern: 振込 + カナ人名 → outsourcing + 発生日前月末調整
|
|
83
|
+
7. No-match → Stage 2 fallback signal
|
|
84
|
+
8. Normalize: 全角 / カタカナ / 半角混在の 摘要
|
|
85
|
+
|
|
86
|
+
## See also
|
|
87
|
+
|
|
88
|
+
- Schema: [`../keyword-dict-schema.json`](../keyword-dict-schema.json)
|
|
89
|
+
- Architecture: [`../../docs/architecture.md`](../../docs/architecture.md)
|
|
90
|
+
- 7 exclusion rules: [`../exclusion-rules/README.md`](../exclusion-rules/README.md) (= Stage 0 = before classifier runs)
|
|
91
|
+
- Strategy: [synapse-arrows-playbook Doc 10](https://github.com/michielinksee/synapse-arrows-playbook/blob/main/04-tooling-gaps/10-kansei-link-cockpit-strategy.md)
|