mimispec 0.2.1

A high-density intent description language for human-AI collaboration
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
# MimiSpec 语法规范 v1.0.0-rc.2

**MimiSpec**(文件后缀 `.mms`)是一门高信息密度的意图描述语言。

核心设计原则:**任何语法子树都可以作为合法的顶层 Fragment 存在**。从一行 `type` 定义到完整的 `module` 树,从单个 `if` 分支到完整的 UI 视图,`.mms` 文件始终合法、始终精确、始终可解析。

> **设计格言**:From Scratch to Full —— 碎片是起点,聚合是过程,完整是结果。

MimiSpec v0.3.1 以**单文件优先**为设计原则:解析器独立处理每个 `.mms` 文件,不强制解析外部依赖。跨文件引用通过 `@import` 显式声明,但链接工作延迟到 IDE 或编译工具阶段,保持解析层的极简与碎片的独立性。

---

## 1. 元语法:槽位、实体与约束

MimiSpec 的语法位置本质上都是**槽位**(slot),等待被填充。槽位由缩进层级界定,同一缩进层级内的语句按顺序排列。

### 1.1 三种核心语法元素

| 元素 | 语义 | 语法 | 示例 |
|------|------|------|------|
| **实体(Entity)** | 槽位中的内容 | 独立存在于 block 中 | `type Order:`, `desc "订单数据"`, `check balance` |
| **占位符(Placeholder)** | 待填充的空白槽位 | `...` | `...` |
| **约束(Constraint)** | 施加于下一个实体的规则 | 写在实体前面,前置附着 | `rule "余额必须大于0"` |

### 1.2 `desc` = 实体占位(自然语言实体)

`desc "..."` **不是修饰符,而是一个独立的实体**。它表示:

> **"这里需要一个东西,具体是什么让 AI 决定,但意图是这个描述。"**

```mimispec
func Pay:
    desc "处理支付:检查余额、扣款、改状态"   # ← desc 是 func body 的一个实体元素
    steps:
        desc "检查买家余额是否充足"             # ← desc 是 steps block 的一个实体元素
        desc "调用支付网关扣款"
        desc "把订单状态改为已支付"
```

`desc` 和 `...` 的关系:
- `...` = "我不知道这里要什么"
- `desc "检查余额"` = "我知道这里要一个检查余额的东西,但具体实现交给 AI"

`desc` 的内容是自然语言,解析器不做语义解析,直接透传给 AI。

### 1.3 `rule` = 约束声明(前置附着)

`rule "..."` **不是实体,而是施加于下一个实体的约束**。它表示:

> **"紧随其后的实体,必须满足这条约束。"**

```mimispec
rule "支付必须幂等"
func Pay:
    steps:
        check balance
```

`rule "支付必须幂等"` 附着于 `func Pay`,约束整个函数的实现。

**附着规则**:

1. 连续的 `rule` 语句收集为一个约束列表,全部附着给下一个实体。  
   这里的“连续”允许由普通换行分隔;只要中间没有空行,就视为同一约束链。
2. 空行阻断附着链,未被接收的 `rule` 变为当前层级全局约束:
   - 文件顶层 → `file.rules`
   - `module` body 内 → `module.rules`
   - `func` body 内 → `func.rules`
3. `//` 注释对 parser 来说是透明的,但**独占一行的 `//` 注释会被 lexer 视为空行**,因此也能阻断约束链。阅读器可以把它当作规则分组的标题,但这不是语法要求。
4. `rule` 约束的是**整个实体及其内部所有内容**(递归约束)。

```mimispec
// 文件级约束组
rule "系统必须支持幂等操作"
rule "所有转换必须有日志"

// module 级约束组
rule "模块必须可回滚"
module Shop:
    // 本 module 的约束组
    rule "金额不能为负数"
    rule "订单金额必须大于 0"

    type Order:
        desc "订单数据"
        amount: Money

    // func 级约束组
    rule "支付必须幂等"
    rule "退款必须在有效期内"
    func Pay:
        steps:
            check balance
            charge payment
```

在上例中:

- `系统必须支持幂等操作``所有转换必须有日志` 因空行/注释行未被下一个 `module` 接收,进入 `file.rules`- `模块必须可回滚` 前有空行,也进入 `file.rules`- `金额不能为负数``订单金额必须大于 0` 被空行/注释行阻断,进入 `module Shop.rules`- `支付必须幂等``退款必须在有效期内` 紧跟 `func Pay`(无空行),附着给 `func Pay`
### 1.4 `desc` vs `rule` 的本质区别

| | `desc` | `rule` |
|--|--------|--------|
| **语法角色** | **实体**(block 中的独立元素) | **修饰符**(前置附着于下一个实体) |
| 是否产生内容 | 是(产生一个自然语言占位实体) | 否(只声明约束) |
| AI 如何理解 | "请在这个位置生成一个东西,意图是..." | "请确保下一个东西满足..." |
| 能否独立存在 | 能(`desc "..."` 单独一行合法) | 不能(`rule` 必须附着于下一个实体) |
| 内容是否被解析 | 否(自然语言,透传 AI) | 否(自然语言,透传 AI) |

---

## 2. 文件结构

### 2.1 顶层 Fragment

一个 `.mms` 文件由零个或多个 `Fragment` 组成。每个 Fragment 独立解析,互不影响。

```
Fragment₁

Fragment₂

...
```

空文件是合法的(零个 Fragment)。

### 2.2 Fragment 类型

| Fragment | 首 token | 说明 |
|----------|----------|------|
| `Module` | `module` | 命名空间容器,可嵌套 |
| `TypeDef` | `type` | 枚举或记录定义 |
| `Flow` | `flow` | 状态机转移图 |
| `Func` | `func` | 函数契约与步骤 |
| `Ui` | `ui` | 视图骨架 |
| `Steps` | `steps` / `if` / `for` / `while` / `parasteps` / `desc` | 裸步骤流(顶层的 `desc`、控制流、动作都会解析为单步 Steps Fragment) |
| `Expr` | 表达式首 token | 裸条件/赋值/动作表达式 |
| `UiNode` | `stack` / `parallel` / `"..."` | 裸 UI 节点 |
| `Placeholder` | `...` | 占位符 |

**注意**:v0.3.1 中 `rule` 不再是独立 Fragment(它是前置约束修饰符)。

---

## 3. 关键字

全部小写,不能用作标识符。

```
module  type    flow    func    steps
requires ensures math    if      else    for
while   >>>     desc    on      with    error
and     or      not     in      done    exit
stack   parallel binds
parasteps
rule
true    false
```

### 3.1 跨文件指令 @import

`@import` 是唯一允许出现在 `.mms` 文件顶部的文件级指令,位于所有 Fragment 之前。

```mimispec
@import "path/to/other.mms"
```

- 可声明多次,每行一个
- 路径为字符串字面量,解析器只校验语法格式,不解析实际文件
- 被引用文件中的定义(`type``func` 等)在当前文件中可直接用标识符访问,无需前缀
- 链接与冲突消解由 IDE 或编译工具在后续阶段完成

### 3.2 意图后缀(锁定 + 不确定)

任何关键字、标识符或字符串末尾可紧接 **锁定后缀** 和/或 **不确定后缀**(无空格)。顺序固定为:**先锁定,后不确定**。

**锁定后缀**:

| 标记 | 含义 |
|------|------|
| `$` | 设计锁定:该节点内容已被确认,AI 不得修改 |
| `$$` | 强锁定:需要人类显式解锁才能改动 |

**不确定后缀**:作用对象是其前面的锁定后缀;若无锁定后缀,则作用于节点本身。

| 标记 | 含义 |
|------|------|
| `?` | 不确定 / 请求再审视 |
| `??` | 完全委托 |

**组合后的完整语义**:

| 后缀 | 锁定 | 对锁定/节点的态度 | 说明 |
|------|------|------------------|------|
| (无) || 正常协作 | 人类写的,AI 可优化 |
| `?` || 不确定 | 给我几个选项 |
| `??` || 完全委托 | 我不知道,你全权决定 |
| `$` | 锁定 | 确信 | 人类确认,AI 不得修改 |
| `$$` | 强锁定 | 确信 | 需要人类显式解锁才能改动 |
| `$?` | 锁定 | 不确定 | 我想锁定,但 AI 帮我再看看是否该锁 |
| `$??` | 锁定 | 完全委托 | 我锁定了,但 AI 全权决定是否保留锁 |
| `$$?` | 强锁定 | 不确定 | 我想强锁,但 AI 帮我再审视 |
| `$$??` | 强锁定 | 完全委托 | 我强锁了,但 AI 全权决定是否保留强锁 |

**顺序规则**:锁定后缀必须在不确定后缀之前。`?$` / `?$$` / `??$` / `??$$` 等顺序非法。

> 示例:
> ```mimispec
> rule$ "支付必须幂等"      # AI 不得修改这条 rule
> rule$? "支付必须幂等"     # 用户想锁定,但请 AI 再审视锁定是否合理
> rule$?? "支付必须幂等"    # 用户锁定了,但 AI 可全权决定是否保留锁定
> ```

---

## 4. 词法规则

### 4.1 标识符

- 以字母或下划线开头,后续可接字母、数字、下划线
- 关键字不可作为标识符
- 支持意图后缀:`ident?``ident??``ident$``ident$$``ident$?``ident$??``ident$$?``ident$$??`

### 4.2 字符串字面量

以双引号 `"` 包围的纯文本:

```mimispec
"普通文本"
"包含空格的文本"
"包含 '单引号' 的文本"
```

**重要限制**:
- 字符串**不允许隐式跨行**。未闭合的引号若遇到换行,解析器会立即报 `unterminated string` 错误
- 如需在字符串中表示物理换行,使用转义序列 `\n`

**支持的转义序列**:

| 转义 | 含义 |
|------|------|
| `\\` | 反斜杠 |
| `\"` | 双引号 |
| `\n` | 换行符 |
| `\t` | 制表符 |
| `\r` | 回车符 |

### 4.3 缩进

MimiSpec 使用**基于缩进的块结构**:

- 缩进单位必须是 **4 个空格** 的整数倍(4、8、12...)
- **禁止使用 Tab**
- 同级语句必须对齐在同一缩进层级
- 子块相对父块缩进 4 个空格

### 4.4 注释

单行注释以 `//` 开头,到行尾结束。

```mimispec
// 这是注释
func Pay(): // 行尾注释也可以
    steps:
        charge payment
```

---

## 5. Fragment 规范

### 5.1 module(模块容器)

```mimispec
module ModuleName:
    Entity₁
    Entity₂
    ...
```

- `module` 引导块**必须带冒号**
- 模块内部可以包含任意实体:`Fragment``desc`、以及被 `rule` 前置修饰的任何实体
- `rule` 链可被空行或独占一行的 `//` 注释阻断;阻断后未被接收的 `rule` 变为 `module` 级约束
- 模块 body 中首个 `desc` 作为模块描述;后续 `desc` 会解析为包含单个 Desc step 的 `Steps` Fragment

**示例**:
```mimispec
module Shop:
    desc "订单管理模块,处理下单、支付、退款"

    type OrderStatus: New | Pending | Paid

    rule "支付必须幂等"
    func Pay(order, amount):
        desc "处理支付流程"
        steps:
            desc "检查买家余额"
            desc "调用支付网关"
            desc "更新订单状态"

    module Payment:
        func Refund(order):
            desc "处理退款流程"
            steps:
                desc "验证退款条件"
                desc "恢复库存"
                desc "发起退款"
```

### 5.2 type(类型定义)

`type` 统一承担枚举和记录两种定义。解析器根据内容自动推断:出现 `|` 分隔符即为枚举,出现缩进字段列表即为记录。

**枚举**支持两种形式:

单行(变体 ≤4 时推荐):
```mimispec
type TypeName: VariantA | VariantB | VariantC
```

多行缩进块(变体 >4 时推荐,v0.4+):
```mimispec
type TypeName:
    | VariantA
    | VariantB
    | VariantC
    | VariantD
    | VariantE
```

也支持无 `|` 前缀的裸标识符形式:
```mimispec
type TypeName:
    VariantA
    VariantB
    VariantC
```

解析器自动判断:缩进块内出现 `|` 或裸标识符(无 `:`)→ 枚举;出现 `field: Type` → 记录。块内也允许一行多个式 `A | B | C`。

**记录**:
```mimispec
type RecordName:
    desc "记录描述"
    field1: TypeHint
    field2: TypeHint
```

字段类型提示可为任意标识符,如 `u64`、`list<...>`、`string` 等,仅用于 AI 上下文,不强制实现细节。

**type body 中的实体**:
- `desc "..."` — 类型级自然语言描述实体;仅首个 `desc` 生效,后续 `desc` 被忽略
- `field: TypeHint` — 字段定义实体
- `...` — 占位符
- `rule "..."` 前置 — 约束该类型(字段级 `rule` 前置已实现,会附着给下一个 field)

### 5.3 rule(约束声明)

```mimispec
rule "自然语言约束描述"
```

- **无标签**,内容就是约束本身
- 字符串支持模糊标记:`"..."?``"..."??`
- 必须写在实体前面,作为前置附着修饰符
- 连续多条 `rule` 收集为约束列表,全部附着给下一个实体;普通换行分隔仍视为连续
- 空行或独占一行的 `//` 注释阻断附着链,未附着的 `rule` 变为当前层级全局约束
- 阅读器可将紧邻 rule 链上方的 `//` 注释作为分组标题显示,但注释本身不参与语法

**示例**:
```mimispec
// 全局约束
rule "系统必须支持幂等操作"
rule "所有转换必须有日志"

// module 级约束
rule "模块必须可回滚"
module Shop:
    // 本模块约束
    rule "金额不能为负数"
    rule "订单金额必须大于 0"

    type Order:
        desc "订单数据"
        amount: Money

    // func 级约束
    rule "支付必须幂等"
    rule "退款必须在有效期内"
    func Pay:
        // func body 内约束
        rule "扣款前必须校验余额"
        rule "失败必须记录日志"

        steps:
            check balance
            charge payment
```

### 5.4 flow(状态流)

```mimispec
flow FlowName:
    StateA >>> StateB: desc "说明"
    StateB:
        >>> StateC: desc "..."
```

- `FlowName` 可与某个 `type` 枚举名对应,表明该状态机的作用域
- `>>>` 表示单向转移
- 若一个状态有多个出边,必须用缩进列表表达
- flow entry block 内可以包含 `desc` 实体和 `rule` 前置约束

### 5.5 func(函数)

```mimispec
func 函数名[(参数列表)] [with 能力列表]:
    Entity₁
    Entity₂
    ...
```

- 参数列表 `(参数列表)` 为可选项。无参数时可省略括号
- `with` 能力声明为未来编译期能力检查预留接口,当前可忽略
- func body 可以包含的实体:`desc`(首个为函数描述,后续转为 Desc step)、`requires``ensures``steps``...`,以及**直接写在 body 中的裸 step**(如 `if``for``while`、动作步骤等)
- func body 内的实体可以被 `rule` 前置约束;`rule` 链被空行或独占一行的 `//` 注释阻断后,变为 `func` 级约束

#### 前置/后置条件 (`requires` / `ensures`)

`requires` 和 `ensures` 是 func body 中的**独立实体**。

支持两种模式,通过首字符自动识别:

- **结构化表达式**:不以 `"` 开头,使用字段、比较符和逻辑连接词
  - 支持:`==`, `!=`, `<`, `>`, `<=`, `>=`, `and`, `or`, `not`, `in`
  - 示例:`requires: order.status == Pending and amount > 0`
  - `in` 右侧支持列表字面量:`requires: status in [Pending, Paid]`
- **自然语言字符串**:以 `"` 开头,内部为纯文本,不允许隐式跨行(未闭合引号遇到换行会报错)
  - 示例:`ensures: "payment captured or error"`

#### 步骤块 (`steps`)

步骤块通过缩进包含一系列控制流和动作标签。每个步骤由一行标签表示,可附加 `desc`、`to` 和 `on`。

**基础步骤**:
```mimispec
steps:
    validate input desc "check mandatory fields"
    process data
    return result >>> done
```

**步骤标签中的关键字转义**:

当步骤标签中出现 `on`、`desc`、`error` 等关键字时,可用双引号将冲突词或整句转为字面量:

```mimispec
steps:
    "operate on data"              # 整句引号,避让 on
    check "for" updates            # 单次引号,避让 for
    parse optional "desc"          # 单次引号,避让 desc
```

字符串 `Atom` 是 MimiSpec 标准类型,无需语法扩展。仅在冲突处使用,其余处保持裸标识符。

**`desc` 作为独立步骤**:
```mimispec
steps:
    desc "检查买家余额是否充足"     # ← desc 是独立步骤实体
    desc "调用支付网关扣款"
    desc "把订单状态改为已支付"
```

`desc` 步骤的语义:"这里需要一步,具体实现交给 AI,意图是这个描述。"

**流程转移 (`>>>`)**:
在步骤末尾使用 `>>> 目标`,目标可以是状态名、`done`(正常结束)或 `exit`(异常退出)。

```mimispec
order.status = Paid >>> done
mark order Shipped >>> done
```

**赋值 (`=`)**:
动作步骤可使用 `=` 对字段或变量赋值。语法:`target = value [>>> 目标]`。
- 右侧必须是**简单值**:标识符、字符串、数字、`true`/`false`、列表字面量
- 不允许多重赋值或计算表达式

```mimispec
order.status = Paid >>> done
tags = [Urgent, Internal]
```

**控制流**:
- `if 条件:` + 缩进块,可选 `else:` 分支
- `for 条件:` + 缩进块(如 `for each item in order.items`- `while 条件:` + 缩进块,建议附带 `desc` 说明终止条件(静态检查会提示,但 parser 层面不强制)

**异常回滚 (`on`)**:
紧接在某步骤后(同级缩进),表示该步骤失败时的补偿逻辑。语法:`on 条件:` + 缩进块,块内语法与 `steps` 相同。支持多个 `on` 分支(如 `on timeout:`、`on lock error:`)。

**错误终止 (`error`)**:
`error "消息" [>>> exit]` 表示显式失败,终止当前路径。`>>> exit` 为可选;若省略,仅终止当前分支而不显式标记为异常退出。

#### 完整示例

```mimispec
func Pay(order, amount) with PaymentCap?:
    desc "处理支付:检查余额、扣款、改状态"
    requires: order.status == Pending and amount == order.total
    ensures: order.status == Paid or (order.status == Pending and no side effects)
    steps:
        check funds desc "verify account balance"
        if insufficient:
            error "insufficient funds" >>> exit
        reserve inventory:
            for item in order.items:
                Inventory.reserve(item)
            on reserve failure:
                release reserved items desc "rollback"
                error "inventory error" >>> exit
        charge payment desc "call PSP"
        on charge failure:
            release inventory desc "compensate"
            error "payment failed" >>> exit
        order.status = Paid >>> done
```

### 5.6 ui(视图)

```mimispec
ui ViewName binds Model:
    stack "根容器":
        "文本" desc "说明"
```

`binds` 表示该视图绑定的数据模型。UI 节点支持:
- `stack`(纵向堆叠)和 `parallel`(横向排列)两种布局容器
- 字符串字面量叶子节点
- `error "消息" [desc "说明"]` 错误节点

布局容器 `stack` / `parallel` 后可跟可选的字符串描述标签。

**事件绑定**:
UI 元素可通过 `on <事件>:` 绑定动作,事件名由标识符或字符串字面量表示(如 `tap`、`click`):

```mimispec
"支付按钮" desc "主操作" on tap: Pay(order)
"重试" on "long-press": Retry()
```

### 5.7 steps(步骤流)

`steps` 可作为独立的顶层 Fragment。

```mimispec
steps:
    步骤₁
    步骤₂
    ...
```

**语义**:一个无函数签名的纯步骤流。AI 或工具层可以:
- 将其视为匿名过程
- 将其内联到某个 `func``steps`- 将其作为对话中的"下一步行动"执行

**示例**:
```mimispec
steps:
    validate order desc "检查必填字段"
    if order.total > 1000:
        request approval
    charge payment
    on failure:
        log error
        retry
    order.status = Paid
```

### 5.8 parasteps(并行步骤)

`parasteps` 表示时间上并行执行的步骤块。与 UI 中的 `parallel`(空间横向排列)形成对称。

`parasteps` 内部的动作步骤会并行执行,全部完成后才继续后续步骤。

```mimispec
func LoadDashboard:
    steps:
        parasteps "同时请求多个数据源":
            loadUsers desc "获取用户数据"
            loadOrders desc "获取订单数据"
            loadMetrics desc "获取统计指标"
        combine results >>> done
```

- `parasteps` 后可跟一个可选的字符串标签(如 `"同时请求多个数据源"`),用于说明并行块的意图
- 并行执行内部所有步骤,等待全部完成后执行后续步骤

### 5.9 错误与异常处理

#### error 终止

`error` 终止当前路径,配合 `>>> exit` 表示到达预定义终点(流程失败退出)。

```mimispec
if stock.available < item.qty:
    error "库存不足" >>> exit
```

`>>> exit` 是预定义终点,表示"这道流程做不下去了,直接退出"。

#### on 补偿块

`on` 块紧接在可能失败的步骤之后,用于定义补偿逻辑(回滚/重试/通知)。

```mimispec
charge payment
on gateway error:
    log failure
    error "支付失败" >>> exit
```

```mimispec
steps:
    validate order
    on failure:
        log error
        retry
    order.status = Paid
```

`on` 块与可能失败的步骤同级缩进,表示该步骤失败时的处理预案。

### 5.10 Expr(表达式)

任何条件表达式、赋值表达式或动作表达式都可以作为独立的顶层 Fragment。

```mimispec
order.status == Pending and amount > 0
```

```mimispec
user.role == Admin or user.trustScore >= 80
```

```mimispec
order.status = Paid
```

```mimispec
charge payment desc "调用支付网关"
```

**列表字面量**:
`in` 右侧可以是普通标识符,也可以是列表字面量:

```mimispec
requires: status in [Pending, Paid]
```

列表项限定为简单表达式(标识符、字符串、数字、`true`/`false`)。

**语义**:单行的意图表达。工具层可以:
- 将其作为 `requires` / `ensures` 的候选条件
- 将其作为 `func` 步骤中的某一行
- 将其作为 AI 对话中的"确认点"

### 5.11 UiNode(UI 节点)

任何 UI 节点都可以作为独立的顶层 Fragment。

```mimispec
"支付按钮" desc "主操作" on tap: Pay(order)
```

```mimispec
stack "工具栏":
    "全部" desc "过滤"
    "进行中" desc "过滤"
```

**语义**:独立的 UI 元素描述。工具层可以:
- 将其嵌入到某个 `ui` 视图中
- 将其作为设计系统中的组件复用

### 5.12 Desc(自然语言实体)

`desc "..."` 是**独立的实体**,不是修饰符。它可以出现在任何 block 中,作为自然语言占位。

**在 `module`、`type`、`func` body 中的行为**:
- 首个 `desc` 通常作为容器自身的描述(`module.desc``type.desc``func.desc`- 同一容器内出现多个 `desc` 时,后续 `desc``func` 中变为 `Desc` step;在 `module` 中变为包含单个 `Desc` step 的 `Steps` Fragment;在 `type` 记录体中则被忽略

**在 `steps` 块中的行为**:
`desc` 是独立步骤实体:

```mimispec
func Pay:
    desc "处理支付:检查余额、扣款、改状态"     # func 描述
    steps:
        desc "检查买家余额是否充足"               # Desc step
        desc "调用支付网关扣款"                   # Desc step
        desc "把订单状态改为已支付"               # Desc step
```

**顶层 `desc`**:
文件顶层的 `desc "..."` 实际解析为 `Fragment::Steps { keyword_commitment, steps: [Step::Desc] }`,不是独立的 `Fragment::Desc`。

**顶层 `...`**:
独立的 `...` 解析为 `Fragment::Placeholder { keyword_commitment }`。

**`desc` 与 `...` 的关系**:
- `...` = "我不知道这里要什么"
- `desc "检查余额"` = "我知道这里要一个检查余额的东西,但具体实现交给 AI"

---

### 5.13 math(数学块)

`math:` 是一个**结构化数学表达式块**,用于精确锁定数值、张量、位运算关系与推导。它出现在 `func`、`module`、`type` body 中,与 `requires:` / `ensures:` / `steps:` 平级。

```mimispec
func CrossAttention(query, key, value):
    math:
        d_k = dim(key, -1)
        scores = query @ key.T / sqrt(d_k)
        weights = softmax(scores, -1)
        context = weights @ value
```

#### 语法

```mimispec
math:
    语句₁
    语句₂
    ...
```

每行是一个数学语句,支持两种形式:

- **定义式**`target = expr`
- **表达式/约束**`expr`(如等式、不等式、函数调用)

#### 支持的运算符(按优先级从低到高)

| 优先级 | 运算符 | 说明 |
|--------|--------|------|
| 1 | `or` | 逻辑或 |
| 2 | `and` | 逻辑与 |
| 3 | `== != < > <= >= in` | 比较与成员关系 |
| 4 | `\|` | 按位或 |
| 5 | `^` | 按位异或 |
| 6 | `&` | 按位与 |
| 7 | `<< >>` | 左移 / 右移 |
| 8 | `+ -` | 加 / 减 |
| 9 | `* / @` | 乘 / 除 / 矩阵乘法 |
| 10 | `**` | 幂(右结合) |
| 11 | `-` `~` `not` | 一元负、按位取反、逻辑非 |

#### 数字字面量

math 块中的数字支持整数、小数和科学计数法:

```mimispec
math:
    a = 42
    b = 3.14
    c = 1e-4
    d = 1.5e+3
```

#### 标量算术

```mimispec
math:
    a + b
    a - b
    a * b
    a / b
    a ** b
    -a
```

#### 比较与逻辑

```mimispec
math:
    a == b
    a != b
    a > b
    a >= b
    a < b
    a <= b
    a and b
    a or b
    not a
    a in [1, 2, 3]
```

#### 位运算

```mimispec
math:
    a & b
    a | b
    a ^ b
    ~a
    a << n
    a >> n
```

#### 张量 / 线性代数

```mimispec
math:
    C = A @ B          # 矩阵乘法
    B = A.T            # 转置
    d = dim(x, -1)     # 取维度大小
    s = shape(x)       # 完整形状
    s0 = shape(x, 0)   # 第 0 维大小
    v = x[i]           # 一维索引
    v = x[i, j]        # 多维索引
    v = x[-1]          # 负数索引
```

#### 常用函数

```mimispec
math:
    sqrt(x)
    abs(x)
    exp(x)
    log(x)
    sum(x)
    sum(x, -1)
    mean(x)
    max(x)
    min(x)
    argmax(x, -1)
    argmin(x, -1)
    prod(x)
    variance(x)
    std(x)
    median(x)
    percentile(x, 0.9)
    softmax(x, -1)
    dot(a, b)
    norm(x, 2)
```

#### 微积分

```mimispec
math:
    grad(f, x)
    derivative(f, x)
    partial(f, x)
    jacobian(f, x)
    hessian(f, x)
    integral(f, x, a, b)
```

#### 使用 `math:` 的场景

**形状约束(替代自然语言)**:

```mimispec
# 之前
requires: Q.last_dim == num_heads multiplied by head_dim

# 之后
requires: dim(Q, -1) == num_heads * head_dim
```

**函数内推导**:

```mimispec
func CrossAttention(query, key, value):
    requires: query.dim == 2 and key.dim == 2 and value.dim == 2
    math:
        d_k = dim(key, -1)
        scores = query @ key.T / sqrt(d_k)
        weights = softmax(scores, -1)
        context = weights @ value
        context.shape == [query.shape[0], dim(value, -1)]
```

**模块级不变量**:

```mimispec
module Physics:
    math:
        E = m * c ** 2
```

**类型级约束**:

```mimispec
type Rectangle:
    width: Number
    height: Number
    math:
        area == width * height
```

#### `desc` 的关系

`math:` 负责**可解析、可静态检查**的精确数学意图;`desc "..."` 负责人类可读的自然语言说明(可包含 LaTeX)。两者互补:

```mimispec
func CrossAttention(query, key, value):
    desc "标准的 scaled dot-product attention"
    math:
        scores = query @ key.T / sqrt(dim(key, -1))
```

#### 注意

- `math:` 内不使用 LaTeX;需要排版公式时请用 `desc`
- `=``math:` 内表示**定义/等式**`==` 表示**相等比较**
- `|``type` 枚举体中表示变体分隔,在 `math:` 内表示按位或,由上下文区分

---

## 6. 聚合语法

### 6.1 `...` 占位符

表示"这里的内容待填充"。

```mimispec
func Pay(order, amount):
    requires: ...
    steps:
        check funds
        ...
        order.status = Paid >>> done
```

`...` 可以出现在:
- `requires` / `ensures` 的值位置
- `steps` 块中的任意步骤位置
- `module` 块中的任意位置
- `type` body 中的任意位置
- `func` body 中的任意位置
- 顶层 Fragment 位置

### 6.2 `@import` 跨文件引用

碎片文件可以通过 `@import` 建立跨文件依赖,不破坏碎片的独立性。

```mimispec
@import "common/types.mms"

module UserDomain:
    func GetUser(id):
        requires: id > 0
        steps:
            query database
            return user >>> done
```

`@import` 表示"引用某个在别处定义的文件"。即使被引用的文件不存在于当前目录,该文件仍然是**合法但不可链接**的(parseable but not linkable)。

---

## 7. 模块与引用

MimiSpec v0.3.1 以**单文件优先**为设计原则:同一文件内通过命名空间直接引用,无需前缀。若需引用其他 `.mms` 文件中的定义,使用文件顶部的 `@import` 指令显式声明。

### 7.1 模块内引用

同一文件内,直接使用标识符引用:

```mimispec
module Shop:
    type OrderStatus: New | Paid

    func Pay(order):
        requires: order.status in [New]
        steps:
            order.status = Paid
```

### 7.2 嵌套模块

```mimispec
module Shop:
    module Payment:
        func Pay(): ...

    module Shipping:
        func Ship(): ...
```

跨嵌套模块引用使用点号路径:`Shop.Payment.Pay`

### 7.3 跨文件引用

通过 `@import` 引入其他 `.mms` 文件后,当前文件可直接使用被引入文件中的定义:

```mimispec
// utils.mms
func ValidateEmail(email):
    requires: email != ""
    steps:
        check format >>> done
```

```mimispec
// user.mms
@import "utils.mms"

module UserDomain:
    func Register(email):
        steps:
            ValidateEmail(email)
            persist user >>> done
```

跨文件引用保持**扁平命名空间**:被引入的标识符在当前文件中直接可见。若出现命名冲突,工具层应提示歧义,用户可通过限定路径(如 `ModuleName.ident`)解决。

---

## 8. 静态检查规则

1. **碎片合法性**:任何 Fragment 独立解析时是否合法
2. **`...` 密度**:文件中 `...` 比例过高时提示"请先完成核心结构"
3. **渐进式完整度**:IDE 可显示当前文件处于哪个聚合阶段(碎片/片段/模块/项目)
4. **引用可达性**`@import` 引用的目标文件是否在链接阶段可解析
5. **状态覆盖**`flow` 是否覆盖关联 `type` 的所有枚举值(通过命名约定关联)
6. **分支完备性**`if` 是否缺少 `else` 或明确占位
7. **循环终止**:建议 `while` 附带 `desc` 说明终止条件(parser 层面不强制,静态检查可提示)
8. **契约一致性**`func``ensures` 是否与内部 `error` 路径矛盾
9. **锁定与不确定密度**`?`/`??`/`$`/`$$` 比例过高时提示澄清;`?$` 等非法顺序报错
10. **rule 悬空**:block 末尾的 `rule` 未被任何实体接收时提示

---

## 9. 解析器接口

### 9.1 AST 结构

```rust
/// 源文件根节点
pub struct File {
    pub imports: Vec<String>,
    pub rules: Vec<RuleDef>,        // 全局约束(未被附着的 rule)
    pub fragments: Vec<Fragment>,
}

pub enum Fragment {
    Module { module: Module },
    TypeDef { typedef: TypeDef },
    Flow { flow: FlowDef },
    Func { func: FuncDef },
    Ui { ui: UiDef },
    Steps {
        keyword_commitment: Commitment,
        steps: Vec<Step>,
    },
    Expr { expr: Expr },
    UiNode { node: UiNode },
    Placeholder { keyword_commitment: Commitment },
}

/// 约束声明(前置附着于下一个实体)
pub struct RuleDef {
    pub desc: Desc,
    pub keyword_commitment: Commitment,
    pub line: usize,
}

/// 描述实体
pub struct Desc {
    pub need_commitment: Commitment,
    pub content: FString,
}
```

### 9.2 解析入口

```rust
/// 解析完整文件(提取 @import 并解析 Fragment 组合)
pub fn parse(source: &str) -> ParseResult

/// 解析单个 Fragment(用于 IDE 片段验证)
pub fn parse_fragment(source: &str) -> ParseResult

/// 词法分析
pub fn tokenize(source: &str) -> Result<Vec<Token>, ParseError>
```

---

## 10. 关键字速查表

| 类别 | 关键字 |
|------|--------|
| 容器 | `module` |
| 结构 | `type`, `flow`, `func`, `steps`, `ui` |
| 实体 | `desc` |
| 约束 | `rule` |
| 规则/条件 | `requires`, `ensures` |
| 数学 | `math` |
| 控制流 | `if`, `else`, `for`, `while`, `on` |
| 布局 | `stack`, `parallel`, `binds` |
| 转移/终点 | `>>>`, `done`, `exit` |
| 能力 | `with` |
| 错误 | `error` |
| 逻辑 | `and`, `or`, `not`, `in` |
| 布尔 | `true`, `false` |
| 文件指令 | `@import` |
| 聚合 | `...` |
| 并行 | `parasteps` |
| 意图/锁定 | `?`, `??`, `$`, `$$` (后缀;可组合为 `$?`, `$$?`, `$??`, `$$??`|

---

## 11. 示例:从零到完整的渐进式蓝图

### 阶段 1 —— 纯意图(desc-only)

```mimispec
// shop.mms —— 阶段 1:完全委托 AI
module?? Shop:
    type?? Order:
        desc?? "订单数据,包含买家、商品、金额和状态"

    rule?? "支付不能重复扣款"
    rule?? "取消订单后库存必须恢复"

    func?? Pay:
        desc?? "处理支付:检查余额、扣款、改状态"
        steps:
            desc?? "检查买家余额是否充足"
            desc?? "调用支付网关扣款"
            desc?? "把订单状态改为已支付"

    func?? Refund:
        desc?? "处理退款:验证条件、恢复库存、退款"
        steps:
            desc?? "验证退款条件"
            desc?? "恢复库存"
            desc?? "发起退款"
```

### 阶段 2 —— 部分结构化

```mimispec
// shop.mms —— 阶段 2:加入类型和约束
module Shop:
    desc "订单管理模块"

    type OrderStatus: New | Pending | Paid | Shipped | Cancelled

    rule "支付必须幂等"
    rule "库存不能为负"

    func Pay(order, amount):
        desc "处理支付流程"
        requires: order.status == Pending
        steps:
            check balance desc "检查余额"
            charge payment desc "调用支付网关"
            order.status = Paid >>> done

    func Refund(order):
        desc "处理退款流程"
        requires: order.status in [Paid, Shipped]
        steps:
            validate conditions
            restore inventory
            initiate refund >>> done
```

### 阶段 3 —— 完整模块

```mimispec
// shop.mms —— 阶段 3:完整蓝图
module OrderDomain:
    desc "订单域:管理订单生命周期"

    type OrderStatus: New | Pending | Paid | Shipped | Cancelled

    rule "支付幂等"
    rule "取消后库存必须恢复"
    rule "退款必须在有效期内"

    flow OrderLifecycle:
        New >>> Pending: desc "客户提交"
        Pending:
            >>> Paid: desc "支付成功"
            >>> Cancelled: desc "客户取消"
        Paid >>> Shipped: desc "已发货"
        Shipped >>> Delivered: desc "已送达"

    func ProcessOrder(order):
        desc "处理订单"
        requires: order.status == New
        ensures: order.status in [Paid, Cancelled]
        steps:
            check inventory
            if stock < order.qty:
                error "out of stock"
            charge payment
            on failure:
                refund
                error "payment failed" >>> exit
            order.status = Paid >>> done

    func CancelOrder(order):
        desc "取消订单"
        requires: order.status in [New, Pending]
        steps:
            restore inventory
            order.status = Cancelled >>> done

    ui OrderPanel binds order:
        stack "订单面板":
            "订单 #order.id" desc "标题"
            parallel "操作栏":
                "支付" desc "按钮" on tap: ProcessOrder(order)
                "取消" desc "按钮" on tap: CancelOrder(order)
```

### 阶段 4 —— 多模块单文件

```mimispec
// shop.mms —— 阶段 4(单文件完整项目)
module OrderDomain:
    type OrderStatus: New | Pending | Paid | Shipped | Cancelled

    func ProcessOrder(order):
        requires: order.status == New
        ensures: order.status in [Paid, Cancelled]
        steps:
            check inventory
            if stock < order.qty:
                error "out of stock"
            charge payment
            on failure:
                refund
                error "payment failed" >>> exit
            order.status = Paid >>> done

module PaymentDomain:
    func Pay(order, amount):
        requires: order.status == Pending
        ensures: order.status == Paid
        steps:
            verify funds
            process transaction
            order.status = Paid >>> done

module ShippingDomain:
    func Ship(order):
        requires: order.status == Paid
        steps:
            allocate warehouse
            dispatch courier
            order.status = Shipped >>> done
```

### 阶段 5 —— 跨文件引用

```mimispec
// types.mms
type OrderStatus: New | Pending | Paid | Shipped | Cancelled

type Order:
    id: u64
    status: OrderStatus
```

```mimispec
// shop.mms
@import "types.mms"

module Shop:
    func ProcessOrder(order):
        requires: order.status == New
        ensures: order.status in [Paid, Cancelled]
        steps:
            check inventory
            if stock < order.qty:
                error "out of stock"
            charge payment
            on failure:
                refund
                error "payment failed" >>> exit
            order.status = Paid >>> done
```

**关键洞察**:阶段 1 到阶段 5 的 `.mms` 文件,每一阶段都是合法的。解析器不因"不完整"而拒绝,只因"语法错误"而拒绝。`@import` 使得碎片可以跨文件聚合,而解析器本身不强制链接,保持了"合法但不可链接"的渐进式特性。

---

## 附录:v0.3 → v0.3.1 变更摘要

| 变更项 | v0.3 | v0.3.1 |
|--------|------|--------|
| `desc` 语义 | 修饰符(后缀) | **实体占位**(独立元素) |
| `rule` 语法 | `rule Label: "描述"` | `rule "描述"`**无标签**|
| `rule` 语义 | 独立 Fragment | **前置约束修饰符** |
| `rule` 附着 || 连续 rule 收集,附着于下一个实体;空行阻断 |
| `type` body | fields / enum only | 支持 `desc` 实体和 `rule` 前置 |
| `func` body | requires/ensures/steps | 支持 `desc` 实体和 `rule` 前置 |
| `steps` | action/assign/control flow | 支持 `desc` 作为独立步骤 |
| `Fragment::Rule` | 存在 | **删除**(rule 不再是 Fragment) |
| `File` | imports + fragments | imports + **rules** + fragments |

---

## 附录:v0.3.1 → v1.0.0-rc.1 变更摘要

| 变更项 | v0.3.1 | v1.0.0-rc.1 |
|--------|--------|-------------|
| 后缀维度 | 仅不确定后缀 `?` / `??` | 增加锁定后缀 `$` / `$$`,形成二维组合后缀 |
| 后缀顺序 | `?` / `??` 直接附加 | 锁定必须在不确定之前:`$?` / `$$?` / `$??` / `$$??` 合法;`?$` / `?$$` 等非法 |
| `$` / `$$` | 不存在 | 设计锁定 / 强锁定;AI 不得删除锁,但可在锁后追加 `?` / `??` |
| 静态检查 | 模糊密度 | 锁定与不确定密度、非法后缀顺序检查 |