Japanese Input Method System for Linux, macOS, Neural Kana-Kanji Conversion Engine
This report summarizes scanner evidence for togatoga/karukan, a Rust project with 751 GitHub stars. SynthScan examined 108,574 lines of code across 148 source files, recording 118 pattern matches distributed across 10 syntactic categories. The legacy adjusted pattern signal is 1.5 (Low pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Payload schema: 1.0.0 · Engine: 2.0.0 · Scoring: heuristic-density-v1 · Scan date: 2026-10-31.
Can maintainers explain intent, assumptions, and trade-offs? 103 finding(s).
Are imports declared and package/API names verified? 3 finding(s).
Are wrappers, guards, and repeated structures necessary? 13 finding(s).
Which changes need focused human review? 118 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 118 distinct pattern matches across 10 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | karukan-engine/data/single_kanji.yml | 1 | # Single-kanji conversion data: たか → 高, 嵩, 鷹, … one kanji at a time. | COMMENT |
| LOW | karukan-engine/src/learning.rs | 21 | } | COMMENT |
| LOW | karukan-engine/src/dict.rs | 141 | /// Format: | COMMENT |
| LOW | karukan-engine/src/width.rs | 1 | //! Which width a character comes out at: half (`(`, `?`, `1`) or full | COMMENT |
| LOW | karukan-engine/src/width.rs | 21 | /// The width a group comes out at. | COMMENT |
| LOW | karukan-engine/src/kana.rs | 1 | use unicode_normalization::UnicodeNormalization; | COMMENT |
| LOW | karukan-engine/src/kana.rs | 21 | /// True if the text contains any hiragana or katakana **letter**. | COMMENT |
| LOW | karukan-engine/src/romaji/style.rs | 1 | //! Which symbol a key types: the `,` `.` `/` `[` `]` keys have more than | COMMENT |
| LOW | karukan-engine/src/rewriter/symbol.rs | 1 | //! Symbol rewriter — given a typed symbol or hiragana reading, emit related | COMMENT |
| LOW | karukan-engine/src/rewriter/symbol.rs | 21 | //! `scripts/symbols_porter.py`, driving job (2). Re-running the porter | COMMENT |
| LOW | karukan-engine/src/rewriter/emoji.rs | 1 | //! Emoji rewriter — surfaces emoji candidates from two input paths. | COMMENT |
| LOW | karukan-engine/src/rewriter/emoji.rs | 21 | //! 2. **Earliest match position** in the trigger (ascending). | COMMENT |
| LOW | karukan-engine/src/rewriter/emoji.rs | 121 | /// `min()` selects the most relevant: longer contiguous runs come | COMMENT |
| LOW | karukan-engine/src/rewriter/number.rs | 1 | //! Number rewriter — expand a numeric candidate into related styles. | COMMENT |
| LOW | karukan-engine/src/rewriter/single_kanji.rs | 1 | //! Single-kanji rewriter: the reading as one kanji at a time (たか → 高, | COMMENT |
| LOW | karukan-engine/src/rewriter/alphabet.rs | 1 | //! Alphabet width/case rewriter — for ASCII or full-width alphabetic input, | COMMENT |
| LOW | karukan-engine/src/rewriter/date.rs | 1 | //! Date rewriter — turn a registered phrase (きょう, あした, いま, …) into | COMMENT |
| LOW | karukan-engine/src/rewriter/date.rs | 21 | pub struct DateConfig { | COMMENT |
| LOW | karukan-engine/src/rewriter/mod.rs | 1 | //! Candidate rewriters: produce additional variants from existing conversion candidates. | COMMENT |
| LOW | karukan-engine/src/rewriter/half_katakana.rs | 1 | //! Katakana form rewriter — produces full-width and half-width katakana variants. | COMMENT |
| LOW | karukan-engine/src/kanji/hf_download.rs | 1 | //! HuggingFace model download utilities | COMMENT |
| LOW | karukan-engine/src/kanji/hf_download.rs | 21 | /// unreachable host was retried for minutes — each attempt eats a full OS | COMMENT |
| LOW | karukan-engine/src/kanji/hf_download.rs | 41 | PATHS.get_or_init(Mutex::default) | COMMENT |
| LOW | scripts/single_kanji_porter.py | 161 | # Single-kanji conversion data: たか → 高, 嵩, 鷹, … one kanji at a time. | COMMENT |
| LOW | scripts/emoji_porter.py | 221 | # Extra hiragana readings to append onto Mozc's table. | COMMENT |
| LOW | scripts/emoji_porter.py | 241 | # from Mozc's `romanji-hiragana.tsv` because: | COMMENT |
| LOW | scripts/emoji_porter.py | 461 | COMMENT | |
| LOW | karukan-cli/src/bin/sudachi_dict.rs | 21 | /// | COMMENT |
| LOW | karukan-cli/src/bin/server.rs | 21 | COMMENT | |
| LOW | karukan-cli/src/bin/dict.rs | 21 | } | COMMENT |
| LOW | karukan-cli/src/bin/dict.rs | 41 | /// Input format: json or mozc (auto-detected from extension if omitted) | COMMENT |
| LOW | karukan-im/fcitx5/src/lib.rs | 1 | //! karukan-fcitx5: fcitx5 addon for the Karukan Japanese IME | COMMENT |
| LOW | karukan-im/macos/scripts/generate_icons.swift | 1 | #!/usr/bin/env swift | COMMENT |
| LOW | karukan-im/macos/Sources/KarukanIME/KeyCodeMap.swift | 121 | /// before they reach the input context, and mouse events never reach an | COMMENT |
| LOW | …/macos/Sources/KarukanIME/KarukanInputController.swift | 201 | } | COMMENT |
| LOW | karukan-im/core/config/default.toml | 1 | # Karukan IME デフォルト設定 | COMMENT |
| LOW | karukan-im/core/config/default.toml | 21 | # この数までの記号は区切らずに一緒に変換されるため、「おい、お前だよ」が | COMMENT |
| LOW | karukan-im/core/config/default.toml | 41 | beam_width = 3 | COMMENT |
| LOW | karukan-im/core/config/default.toml | 81 | # 候補ウィンドウをいつ開くか。"always" は入力中から常時、"conversion" は Space で | COMMENT |
| LOW | karukan-im/core/config/default.toml | 101 | # かな入力中に出力される文字の幅。文字の種類ごとに "half"(半角)か | COMMENT |
| LOW | karukan-im/core/src/core/keycode.rs | 161 | COMMENT | |
| LOW | karukan-im/core/src/core/preedit.rs | 1 | //! Preedit string management | COMMENT |
| LOW | karukan-im/core/src/core/candidate.rs | 1 | //! Candidate list management | COMMENT |
| LOW | karukan-im/core/src/core/engine/cache.rs | 1 | //! LRU cache for model conversion results. | COMMENT |
| LOW | karukan-im/core/src/core/engine/types.rs | 61 | #[derive(Debug, Clone)] | COMMENT |
| LOW | karukan-im/core/src/core/engine/types.rs | 81 | /// and the aux mode indicator shows. | COMMENT |
| LOW | karukan-im/core/src/core/engine/types.rs | 181 | pub(in crate::core) struct Converters { | COMMENT |
| LOW | karukan-im/core/src/core/engine/types.rs | 201 | Hiragana, | COMMENT |
| LOW | karukan-im/core/src/core/engine/types.rs | 261 | } | COMMENT |
| LOW | karukan-im/core/src/core/engine/types.rs | 341 | /// Whether a conversion consults the learning cache. Tab asks for | COMMENT |
| LOW | karukan-im/core/src/core/engine/mod.rs | 121 | /// Converters (romaji, kanji, light kanji) | COMMENT |
| LOW | karukan-im/core/src/core/engine/mod.rs | 141 | chunks: Vec<ComposingChunk>, | COMMENT |
| LOW | karukan-im/core/src/core/engine/mod.rs | 461 | // exempt — their events routinely carry their own modifier state. | COMMENT |
| LOW | karukan-im/core/src/core/engine/mod.rs | 521 | /// for text that arrives already converted: the model is prompted with | COMMENT |
| LOW | karukan-im/core/src/core/engine/mod.rs | 541 | .map(|c| if c.is_whitespace() { space } else { c }) | COMMENT |
| LOW | karukan-im/core/src/core/engine/input_buffer.rs | 1 | //! InputBuffer: a recorded element array plus a caret, with every view | COMMENT |
| LOW | karukan-im/core/src/core/engine/input_buffer.rs | 21 | //! right of the cursor are never touched, so nothing combines across the | COMMENT |
| LOW | karukan-im/core/src/core/engine/input_buffer.rs | 321 | /// one element per output character. | COMMENT |
| LOW | karukan-im/core/src/core/engine/filter.rs | 1 | //! Source-filtered candidate views (Ctrl+R / Ctrl+T). | COMMENT |
| LOW | karukan-im/core/src/core/engine/filter.rs | 161 | // One dictionary view over both dictionaries: usually the user | COMMENT |
| 10 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/integration/test_fcitx5_addon.sh | 29 | # ------------------------------------------------------- | COMMENT |
| MEDIUM | tests/integration/test_fcitx5_addon.sh | 31 | # ------------------------------------------------------- | COMMENT |
| MEDIUM | tests/integration/test_fcitx5_addon.sh | 61 | # ------------------------------------------------------- | COMMENT |
| MEDIUM | tests/integration/test_fcitx5_addon.sh | 63 | # ------------------------------------------------------- | COMMENT |
| MEDIUM | tests/integration/test_fcitx5_addon.sh | 87 | # ------------------------------------------------------- | COMMENT |
| MEDIUM | tests/integration/test_fcitx5_addon.sh | 89 | # ------------------------------------------------------- | COMMENT |
| MEDIUM | tests/integration/test_fcitx5_addon.sh | 119 | # ------------------------------------------------------- | COMMENT |
| MEDIUM | tests/integration/test_fcitx5_addon.sh | 121 | # ------------------------------------------------------- | COMMENT |
| MEDIUM | tests/integration/test_fcitx5_addon.sh | 166 | # ------------------------------------------------------- | COMMENT |
| MEDIUM | tests/integration/test_fcitx5_addon.sh | 168 | # ------------------------------------------------------- | COMMENT |
| MEDIUM | karukan-engine/data/symbols.yml | 904 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | karukan-engine/data/symbols.yml | 912 | # --------------------------------------------------------------------------- | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | karukan-engine/src/kanji/llamacpp.rs | 287 | // Step 1: Process input tokens for ALL sequences in one batch | COMMENT |
| LOW⚡ | karukan-engine/src/kanji/llamacpp.rs | 301 | // Step 2: Get top-k initial tokens (from any seq, all have same logits at this point) | COMMENT |
| LOW⚡ | karukan-engine/src/kanji/llamacpp.rs | 304 | // Step 3: Initialize beam state. A beam whose initial token is | COMMENT |
| LOW⚡ | karukan-engine/src/kanji/llamacpp.rs | 313 | // Step 4: Add initial tokens to each beam's sequence | COMMENT |
| LOW | karukan-engine/src/kanji/llamacpp.rs | 327 | // Step 5: Generate tokens for all beams in parallel. Greedy sampling | COMMENT |
| LOW | karukan-engine/src/kanji/llamacpp.rs | 421 | // Step 1: decode the prompt once into slot 0 and read its logits. | COMMENT |
| LOW | karukan-engine/src/kanji/llamacpp.rs | 442 | // Step 2: Main beam search loop | COMMENT |
| LOW | karukan-cli/static/app.js | 232 | // Step 1: Romaji -> Hiragana | COMMENT |
| LOW | karukan-cli/static/app.js | 257 | // Step 2: Hiragana -> Kanji (debounced) | COMMENT |
| LOW⚡ | karukan-cli/src/bin/sudachi_dict.rs | 91 | // Step 1: Parse CSV files | COMMENT |
| LOW⚡ | karukan-cli/src/bin/sudachi_dict.rs | 98 | // Step 2: Convert to sorted entries | COMMENT |
| LOW | karukan-cli/src/bin/sudachi_dict.rs | 117 | // Step 3: Score with model or use Sudachi cost directly | COMMENT |
| LOW | karukan-cli/src/bin/sudachi_dict.rs | 140 | // Step 4: Write JSON output | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | karukan-engine/src/kanji/llamacpp.rs | 287 | // Step 1: Process input tokens for ALL sequences in one batch | COMMENT |
| LOW⚡ | karukan-engine/src/kanji/llamacpp.rs | 301 | // Step 2: Get top-k initial tokens (from any seq, all have same logits at this point) | COMMENT |
| LOW⚡ | karukan-engine/src/kanji/llamacpp.rs | 304 | // Step 3: Initialize beam state. A beam whose initial token is | COMMENT |
| LOW⚡ | karukan-engine/src/kanji/llamacpp.rs | 313 | // Step 4: Add initial tokens to each beam's sequence | COMMENT |
| LOW | karukan-engine/src/kanji/llamacpp.rs | 327 | // Step 5: Generate tokens for all beams in parallel. Greedy sampling | COMMENT |
| LOW | karukan-engine/src/kanji/llamacpp.rs | 421 | // Step 1: decode the prompt once into slot 0 and read its logits. | COMMENT |
| LOW | karukan-engine/src/kanji/llamacpp.rs | 442 | // Step 2: Main beam search loop | COMMENT |
| LOW | karukan-cli/static/app.js | 232 | // Step 1: Romaji -> Hiragana | COMMENT |
| LOW | karukan-cli/static/app.js | 257 | // Step 2: Hiragana -> Kanji (debounced) | COMMENT |
| LOW⚡ | karukan-cli/src/bin/sudachi_dict.rs | 91 | // Step 1: Parse CSV files | COMMENT |
| LOW⚡ | karukan-cli/src/bin/sudachi_dict.rs | 98 | // Step 2: Convert to sorted entries | COMMENT |
| LOW | karukan-cli/src/bin/sudachi_dict.rs | 117 | // Step 3: Score with model or use Sudachi cost directly | COMMENT |
| LOW | karukan-cli/src/bin/sudachi_dict.rs | 140 | // Step 4: Write JSON output | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | scripts/single_kanji_porter.py | 121 | CODE | |
| LOW | scripts/emoji_porter.py | 332 | CODE | |
| LOW | scripts/emoji_porter.py | 424 | CODE | |
| LOW | scripts/emoji_porter.py | 616 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | karukan-engine/src/rewriter/emoji.rs | 412 | // ---------- guardrails ---------- | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | scripts/emoji_porter.py | 559 | scalar (numbers like `+1`, booleans, null) so it round-trips back | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | scripts/single_kanji_porter.py | 37 | CODE | |
| LOW | scripts/emoji_porter.py | 51 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/integration/run_fcitx5_test.sh | 4 | # Usage: | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | karukan-cli/static/app.js | 268 | async function handleDirectHiraganaInput(e) { | CODE |