diff --git a/docs/smalruby-dncl-spec.ja.md b/docs/smalruby-dncl-spec.ja.md
new file mode 100644
index 00000000000..acb61366a16
--- /dev/null
+++ b/docs/smalruby-dncl-spec.ja.md
@@ -0,0 +1,561 @@
+# Smalruby 日本語モード(DNCL)言語仕様
+
+このドキュメントは、smalruby3-editor の **日本語モード(DNCLモード)** で対応している構文と機能を定義します。
+ソースコードの `packages/scratch-gui/src/lib/dncl/`(DNCL ↔ Ruby トランスパイラ)と `packages/scratch-gui/src/containers/ruby-tab/dncl-mode.js`(Monaco エディタ言語定義)に基づいています。
+
+> **注意**: 本ドキュメントは **smalruby3-editor における実装**を正として記載しています。大学入学共通テスト手順記述標準言語(DNCLv2)とは異なる点があります。差分は [DNCLv2 との違い](#7-dnclv2-との違い) を参照してください。
+
+## 1. 概要
+
+smalruby の日本語モード(DNCLモード)は、大学入学共通テスト手順記述標準言語(DNCL)を参考にした日本語ベースのプログラミング言語です。日本語で記述したコードは内部的に Ruby コードにトランスパイルされ、さらに Scratch ブロックに変換されて実行されます。
+
+### 動作の仕組み
+
+```
+DNCL コード → (dncl-to-ruby.js) → Ruby コード → (ruby-to-blocks-converter) → Scratch ブロック → 実行
+```
+
+ブロック → Ruby → DNCL の逆方向の変換も可能です(`ruby-to-dncl.js`)。
+
+### 標準 DNCL(DNCLv2)との主な違い
+
+- **ブロック終端が日本語キーワード**(`を実行する`、`を繰り返す`、`と定義する`)であり、コロン `:` は使わない
+- **条件分岐の末尾にコロンがない**(`もし 条件 ならば` であり、`もし 条件 ならば:` ではない)
+- 内部的に Scratch ブロックに変換されるため、**使用できる機能が Scratch の範囲に限定される**
+- 変数に `@` や `$` プレフィックスは使えない(Ruby の変数記法は自動的に処理される)
+
+## 2. プログラム構造
+
+### トップレベル構造
+
+DNCL モードのプログラムは、文(Statement)の連続で構成されます。class 定義や module 定義は使用しません。
+
+```
+# 変数の初期化
+a = 0
+
+# メインロジック
+もし a > 0 ならば
+ 表示する(a)
+を実行する
+```
+
+### インデント
+
+ブロック構造はインデントで表現します。制御構造の内部は 2 スペースのインデントが推奨されます。
+
+```
+もし a > 0 ならば
+ 表示する("正の数")
+そうでなければ
+ 表示する("正でない")
+を実行する
+```
+
+### コメント
+
+`#` 以降が行コメントになります。
+
+```
+# これはコメントです
+a = 1 # 行末コメント
+```
+
+## 3. データ型
+
+### リテラル
+
+| 型 | 構文 | 例 | 備考 |
+|---|---|---|---|
+| 整数 | `数字の並び` | `42`, `0`, `-5` | |
+| 浮動小数点数 | `数字.数字` | `3.14`, `1.0` | |
+| 文字列 | `"..."` または `「...」` | `"hello"`, `「テスト」` | `「」` は `""` に自動変換 |
+| 真偽値 | `真` / `偽` | `真`, `偽` | Ruby の `true` / `false` に変換 |
+| 配列 | `[値1, 値2, ...]` | `[1, 5, 10]` | |
+
+### 文字列リテラル
+
+ダブルクォート `"..."` と日本語カギカッコ `「...」` の両方が使えます。カギカッコはトランスパイル時にダブルクォートに変換されます。
+
+```
+a = "hello"
+b = 「こんにちは」 # → "こんにちは" に変換
+```
+
+## 4. 変数
+
+### 命名規則
+
+| 先頭文字 | 内部変換 | 例 | Ruby 変換後 |
+|---|---|---|---|
+| 小文字 (`a-z`) | インスタンス変数 | `a`, `score` | `@a`, `@score` |
+| 大文字(スカラー値) | 名前付き変数 | `A`, `Max` | `@_var_A_`, `@_var_Max_` |
+| 大文字(配列値) | 名前付き配列 | `Kouka`, `Data` | `@_array_Kouka_`, `@_array_Data_` |
+
+大文字で始まる変数名が配列かスカラーかは、ソースコード内で配列リテラルの代入(`X = [...]`)、配列アクセス(`X[i]`)、または `要素数(X)` の使用があるかどうかで自動判定されます。
+
+### 識別子に使える文字
+
+- ASCII 英字(`a-z`, `A-Z`)、数字(`0-9`)、アンダースコア(`_`)
+- ひらがな(`\u3040-\u309F`)、カタカナ(`\u30A0-\u30FF`)、漢字(`\u4E00-\u9FFF`)
+
+### 禁止文字
+
+変数名に `@` や `$` を使うことはできません。使用した場合、バリデーションエラーが表示されます。
+
+```
+# ❌ エラー: 日本語モードでは変数に「@」は使えません
+@a = 10
+
+# ✅ 正しい書き方
+a = 10
+```
+
+### 代入
+
+| 構文 | 例 | Ruby 変換後 |
+|---|---|---|
+| `変数 = 式` | `a = 10` | `@a = 10` |
+| `変数 ← 式` | `a ← 10` | `@a = 10` |
+
+矢印 `←` による代入も使用できます(`=` と同等)。
+
+```
+a = 10 # 通常の代入
+A ← 3 # 矢印による代入
+Kouka = [1, 5, 10] # 配列の初期化
+```
+
+## 5. 演算子
+
+### 算術演算子
+
+| 演算子 | 説明 | 例 | Ruby 変換後 |
+|---|---|---|---|
+| `+` | 加算 / 文字列結合 | `a + b` | `@a + @b` |
+| `-` | 減算 | `a - 1` | `@a - 1` |
+| `*` | 乗算 | `a * 2` | `@a * 2` |
+| `/` | 除算 | `a / 3` | `@a / 3` |
+| `÷` | 除算(全角) | `a ÷ 3` | `@a / 3` |
+| `//` | 整数除算 | `10 // 3` | `(10 / 3).to_i` |
+| `%` | 剰余 | `a % 2` | `@a % 2` |
+
+### 比較演算子
+
+| 演算子 | 説明 | 例 |
+|---|---|---|
+| `=` | 等しい(条件式内) | `a = 10`(※文脈依存) |
+| `==` | 等しい | `a == 10` |
+| `!=` | 等しくない | `a != 0` |
+| `<` | 小さい | `a < 10` |
+| `>` | 大きい | `a > 0` |
+| `<=` | 以下 | `a <= 10` |
+| `>=` | 以上 | `a >= 0` |
+| `≦` | 以下(全角) | `a ≦ 10` |
+| `≧` | 以上(全角) | `a ≧ 0` |
+
+> **注意**: `=` の代入と比較の区別は文脈(文の先頭 = 代入、条件式内 = 比較)で判断されますが、曖昧さを避けるため条件式では `==` の使用を推奨します。
+
+### 論理演算子
+
+| 演算子 | 説明 | 例 | Ruby 変換後 |
+|---|---|---|---|
+| `かつ` | 論理積 | `a > 0 かつ b < 10` | `@a > 0 && @b < 10` |
+| `または` | 論理和 | `a > 0 または b > 0` | `@a > 0 \|\| @b > 0` |
+| `でない` | 論理否定(後置) | `a でない` | `!@a` |
+
+> **注意**: `かつ`、`または`、`でない` はスペースで区切る必要があります。
+
+## 6. 制御構造
+
+### 条件分岐(もし〜ならば)
+
+```
+もし 条件 ならば
+ 文...
+を実行する
+```
+
+`なら` と `ならば` の両方が使えます。ラウンドトリップ変換では `ならば` に正規化されます。
+
+#### if-else
+
+```
+もし 条件 ならば
+ 文...
+そうでなければ
+ 文...
+を実行する
+```
+
+#### if-elsif-else
+
+```
+もし 条件1 ならば
+ 文1...
+そうでなくもし 条件2 ならば
+ 文2...
+そうでなければ
+ 文3...
+を実行する
+```
+
+### 繰り返し(条件ループ)
+
+#### 条件の間繰り返す(while ループ)
+
+```
+条件 の間
+ 文...
+を繰り返す
+```
+
+例:
+
+```
+a > 0 の間
+ a = a - 1
+を繰り返す
+```
+
+#### 範囲繰り返し(for ループ)
+
+**昇順(増やしながら):**
+
+```
+変数 を 開始値 から 終了値 まで 増分 ずつ増やしながら
+ 文...
+を繰り返す
+```
+
+例:
+
+```
+i を 1 から 10 まで 1 ずつ増やしながら
+ 表示する(i)
+を繰り返す
+```
+
+**降順(減らしながら):**
+
+```
+変数 を 開始値 から 終了値 まで 減分 ずつ減らしながら
+ 文...
+を繰り返す
+```
+
+例:
+
+```
+i を 10 から 0 まで 1 ずつ減らしながら
+ 表示する(i)
+を繰り返す
+```
+
+> **注意**: 終了値は**含まれます**(inclusive)。`1 から 10 まで` は 1, 2, 3, ..., 10 を繰り返します。
+
+### ブロック終端キーワード
+
+制御構造の種類に応じて、異なる終端キーワードを使います。
+
+| 終端キーワード | 対象 |
+|---|---|
+| `を実行する` | `もし〜ならば`(条件分岐) |
+| `を繰り返す` | `の間`(while ループ)、`ずつ増やしながら/減らしながら`(for ループ) |
+| `と定義する` | `関数〜`(関数定義) |
+
+## 7. 関数
+
+### 関数定義
+
+```
+関数 関数名(引数1, 引数2)
+ 文...
+と定義する
+```
+
+例:
+
+```
+関数 add(a, b)
+ 返す a + b
+と定義する
+```
+
+### 戻り値
+
+```
+返す 式
+```
+
+例:
+
+```
+関数 f(x)
+ 返す x * 2
+と定義する
+```
+
+## 8. 組み込み関数
+
+### 入出力
+
+| 関数 | 説明 | 例 | Ruby 変換後 |
+|---|---|---|---|
+| `表示する(式)` | 値を表示する | `表示する(a)` | `say(@a, 1)` |
+| `【外部からの入力】` | 外部からの入力を受け取る | `a = 【外部からの入力】` | `ask_and_wait("")`
`@a = answer` |
+
+`表示する` は複数の引数を受け取れます:
+
+```
+表示する(a, b, c) # → say(@a, @b, @c, 1)
+```
+
+`【外部からの入力】` は代入文の右辺で使用し、Ruby では 2 行に展開されます:
+
+```
+a = 【外部からの入力】
+# ↓ Ruby 変換後
+# ask_and_wait("")
+# @a = answer
+```
+
+### 型変換
+
+| 関数 | 説明 | 例 | Ruby 変換後 |
+|---|---|---|---|
+| `整数(式)` | 整数に変換(小数点以下切り捨て) | `整数(x)` | `@x.to_i` |
+| `文字列(式)` | 文字列に変換 | `文字列(x)` | `@x.to_s` |
+
+### 数値
+
+| 関数 | 説明 | 例 | Ruby 変換後 |
+|---|---|---|---|
+| `乱数(n)` | 乱数を生成 | `乱数(10)` | `rand(10)` |
+
+### 配列操作
+
+| 関数 | 説明 | 例 | Ruby 変換後 |
+|---|---|---|---|
+| `要素数(配列)` | 配列の要素数を取得 | `要素数(Kouka)` | `@_array_Kouka_.length` |
+
+### 配列アクセス
+
+配列の要素にはインデックス(0 起点)でアクセスします。
+
+```
+Kouka = [1, 5, 10]
+a = Kouka[0] # → 1
+Kouka[0] = 100 # 要素の代入
+```
+
+## 9. ブロックパレット(使用可能なブロック)
+
+DNCL モードでは、Scratch のブロックパレットから使用できるブロックが制限されます。
+
+### 完全に非表示のカテゴリ
+
+- **動き(Motion)** — 非表示
+- **音(Sound)** — 非表示
+
+### 使用可能なブロック
+
+| カテゴリ | 使用可能なブロック |
+|---|---|
+| **イベント** | `旗が押されたとき` のみ |
+| **制御** | `〜秒待つ`, `〜回繰り返す`, `もし〜なら`, `もし〜でなければ`, `〜まで待つ`, `〜まで繰り返す`, `〜を止める` |
+| **演算** | すべて |
+| **見た目** | `〜と言う`(`say`)のみ |
+| **調べる** | `〜と聞いて待つ`(`ask`), `答え`(`answer`)のみ |
+| **変数** | すべて(変数の作成、代入、変化、表示/非表示) |
+| **リスト** | すべて(追加、削除、挿入、置換、取得、検索、長さ、含む、空判定) |
+| **ブロック定義** | すべて(関数定義、関数呼び出し、引数) |
+
+## 10. エディタ機能
+
+### シンタックスハイライト
+
+Monaco エディタで以下の要素がハイライトされます:
+
+| 要素 | トークン種別 | 色の例 |
+|---|---|---|
+| 制御キーワード | `keyword` | `もし`, `ならば`, `を実行する` 等 |
+| 組み込み関数 | `type.identifier` | `表示する`, `要素数` 等 |
+| 論理演算子 | `keyword.operator` | `かつ`, `または`, `でない` |
+| 真偽値 | `constant.language` | `真`, `偽` |
+| 入力プレースホルダ | `keyword` | `【外部からの入力】` |
+| 文字列 | `string` | `"..."`, `「...」` |
+| 数値 | `number` | `42`, `3.14` |
+| コメント | `comment` | `# ...` |
+| 演算子 | `operator` | `÷`, `//`, `≦`, `≧`, `←` |
+
+### オートインデント
+
+以下のキーワードの後で自動的にインデントが増加します:
+
+- `なら` / `ならば`(条件分岐の開始)
+- `そうでなければ`(else 節)
+- `そうでなくもし`(elsif 節)
+- `の間`(while ループ)
+- `ずつ増やしながら` / `ずつ減らしながら`(for ループ)
+- `関数〜`(関数定義)
+
+以下のキーワードでインデントが自動的に減少します:
+
+- `を実行する`
+- `を繰り返す`
+- `と定義する`
+- `そうでなければ`
+- `そうでなくもし`
+
+### 自動補完スニペット
+
+以下のスニペットが入力候補として表示されます:
+
+| トリガー | 展開 |
+|---|---|
+| `もし...ならば` | `もし 条件 ならば`
` `
`を実行する` |
+| `もし...そうでなければ` | `もし 条件 ならば`
` `
`そうでなければ`
` `
`を実行する` |
+| `繰り返し(増やす)` | `i を 1 から 10 まで 1 ずつ増やしながら`
` `
`を繰り返す` |
+| `繰り返し(減らす)` | `i を 10 から 0 まで 1 ずつ減らしながら`
` `
`を繰り返す` |
+| `条件の間繰り返す` | `条件 の間`
` `
`を繰り返す` |
+| `関数定義` | `関数 名前(引数)`
` `
`と定義する` |
+| `表示する` | `表示する()` |
+| `【外部からの入力】` | `変数 = 【外部からの入力】` |
+| `要素数` | `要素数(配列名)` |
+| `整数` | `整数(値)` |
+| `文字列` | `文字列(値)` |
+| `乱数` | `乱数(範囲)` |
+
+### 括弧の自動閉じ
+
+以下のペアが自動で閉じられます:
+
+- `()`, `[]`, `{}`
+- `""`, `''`
+- `「」`, `【】`
+
+## 11. DNCLv2 との違い
+
+smalruby3-editor の日本語モードは DNCLv2 を参考にしていますが、以下の点で異なります。
+
+### 構文の違い
+
+| 項目 | DNCLv2 | smalruby3-editor |
+|---|---|---|
+| 条件分岐の開始 | `もし 条件 ならば:` | `もし 条件 ならば`(コロンなし) |
+| 繰り返しの開始 | `〜の間繰り返す:` | `条件 の間`(末尾の「繰り返す」とコロンなし) |
+| for ループの開始 | `〜ずつ増やしながら繰り返す:` | `〜ずつ増やしながら`(末尾の「繰り返す」とコロンなし) |
+| 関数定義の開始 | `関数名(引数) を定義する:` | `関数 関数名(引数)`(`関数` キーワードが先頭、コロンなし) |
+| ブロック終端 | インデント戻りで暗黙終了 | `を実行する` / `を繰り返す` / `と定義する` で明示終了 |
+| 代入(自然言語風) | `変数 に 式 を入れる` | 未対応(`=` または `←` のみ) |
+| 配列宣言 | `要素数 n の配列 A` | 未対応(配列リテラル `A = [...]` で初期化) |
+| else 節 | `そうでない` | `そうでなければ` |
+| 等価比較 | `=`(条件式内で比較) | `==`(推奨)、`=` も使用可能だが曖昧 |
+
+### 機能の違い
+
+| 項目 | DNCLv2 | smalruby3-editor |
+|---|---|---|
+| 実行環境 | コンソール入出力 | Scratch ステージ上で実行 |
+| 入出力 | `表示する(式)` で標準出力 | `表示する(式)` → `say(式, 1)` で吹き出し表示 |
+| 入力 | `外部からの入力()` | `【外部からの入力】`(隅付きカッコ記法) |
+| 戻り値 | `式 を返す` | `返す 式`(語順が逆) |
+| 整数除算 | `//` | `//`(同じ、`.to_i` に変換) |
+| 全角演算子 | 未定義 | `÷`(除算), `≦`(以下), `≧`(以上), `←`(代入)に対応 |
+| スコープ | グローバル/ローカル | すべて Scratch のスプライト変数に変換 |
+| 動き/音/見た目 | 対象外 | Scratch の一部ブロック(`say` のみ)が使用可能 |
+| 配列操作 | `要素数(A)` 等 | `要素数(A)` 対応、Scratch のリストブロックも使用可能 |
+| イベント駆動 | なし | `旗が押されたとき` ブロックを使用可能 |
+
+### 内部実装の特徴
+
+smalruby3-editor の DNCL モードは、以下のアーキテクチャで動作します:
+
+1. **双方向トランスパイル**: DNCL ↔ Ruby の相互変換が可能(ラウンドトリップ対応)
+2. **ソースマップ**: `【外部からの入力】` が 2 行に展開される際の行番号マッピングを管理
+3. **バリデーション**: `@` や `$` の禁止文字チェックをトランスパイル前に実行
+4. **配列名の自動検出**: ソース全体をスキャンして大文字変数の配列/スカラー判定を行う
+
+## 12. サポートされていない構文
+
+以下の構文は日本語モード(DNCL モード)では**使用できません**:
+
+- class 定義 / module 定義 / include
+- イベントハンドラ(`旗が押されたとき` 以外)
+- 動き関連メソッド(`move`, `turn_right` 等)
+- 音関連メソッド(`play`, `stop_all_sounds` 等)
+- 見た目の大部分(`say` 以外の `think`, `show`, `hide` 等)
+- 調べるの大部分(`ask`/`answer` 以外の `touching?`, `mouse.x` 等)
+- `self.属性 = 値` 形式のプロパティ設定
+- 正規表現
+- `for` / `each` ループ
+- `loop do...end`(無限ループ)
+- `unless` / `case-when`
+- 修飾子 if / unless
+- `super`
+- 複合代入演算子(`+=`, `-=` 等)
+- `「変数 に 式 を入れる」` 形式の自然言語代入(DNCLv2 にはあるが未対応)
+
+## 13. 完全なサンプルプログラム
+
+### FizzBuzz
+
+```
+i を 1 から 30 まで 1 ずつ増やしながら
+ もし i % 15 == 0 ならば
+ 表示する("FizzBuzz")
+ そうでなくもし i % 3 == 0 ならば
+ 表示する("Fizz")
+ そうでなくもし i % 5 == 0 ならば
+ 表示する("Buzz")
+ そうでなければ
+ 表示する(i)
+ を実行する
+を繰り返す
+```
+
+### 配列の合計
+
+```
+Data = [3, 1, 4, 1, 5, 9, 2, 6]
+合計 = 0
+i を 0 から 要素数(Data) - 1 まで 1 ずつ増やしながら
+ 合計 = 合計 + Data[i]
+を繰り返す
+表示する(合計)
+```
+
+### 関数定義と呼び出し
+
+```
+関数 最大値(a, b)
+ もし a > b ならば
+ 返す a
+ そうでなければ
+ 返す b
+ を実行する
+と定義する
+
+x = 【外部からの入力】
+y = 【外部からの入力】
+表示する(最大値(整数(x), 整数(y)))
+```
+
+### 線形探索
+
+```
+Data = [5, 3, 8, 1, 9, 2, 7]
+key = 【外部からの入力】
+key = 整数(key)
+found = 偽
+i を 0 から 要素数(Data) - 1 まで 1 ずつ増やしながら
+ もし Data[i] == key ならば
+ 表示する(文字列(i) + "番目に見つかりました")
+ found = 真
+ を実行する
+を繰り返す
+もし found でない ならば
+ 表示する("見つかりませんでした")
+を実行する
+```