cwLeeDev commited on
Commit
52585d7
ยท
verified ยท
1 Parent(s): c07793c

Add fail-closed real P formula data contract

Browse files
MANIFEST.json CHANGED
@@ -1,11 +1,11 @@
1
  ๏ปฟ{
2
- "schema": "aiflow-hf-research-snapshot-v7",
3
- "generated_at": "2026-07-23T19:59:31.9187849Z",
4
  "track": "R_noncommercial_plus_rejected_P_proxy",
5
  "product_validation": false,
6
  "public_release": true,
7
  "contains_raw_dataset": false,
8
- "tests": "278 passed",
9
  "retracted_paths": [
10
  "models/auxiliary/boundary_auxiliary_head.pt",
11
  "models/auxiliary/seed17/boundary_joint_delta.pt",
@@ -28,6 +28,16 @@
28
  "bytes": 6803,
29
  "sha256": "4f842852093ca46b1942c942fd5e475ca6c19f044ba9e27b6d372f1aed56056e"
30
  },
 
 
 
 
 
 
 
 
 
 
31
  {
32
  "path": "scripts/evaluate_crohme_tray_joint_selector.py",
33
  "bytes": 11671,
@@ -38,16 +48,6 @@
38
  "bytes": 11900,
39
  "sha256": "f32a18c8e7d3a0ea36379293e6be88bfb509b7df99846c38149fb8458e6cc994"
40
  },
41
- {
42
- "path": "reports/RESEARCH_REPORT.md",
43
- "bytes": 31962,
44
- "sha256": "704e9d2af5fc5ef36136a80b0f6d66cd0984c21a254ab937cd9d1cdd5603ce47"
45
- },
46
- {
47
- "path": "reports/p_boundary_joint_seed17.json",
48
- "bytes": 6920,
49
- "sha256": "7af3bb995041e5ea621d3c9535f3552e264860f12a7e6145637849f5cd0220a8"
50
- },
51
  {
52
  "path": "reports/online_casecontext_seed31.json",
53
  "bytes": 33576,
@@ -63,6 +63,16 @@
63
  "bytes": 15740,
64
  "sha256": "27b31da71b9f39f7ded38aa1ce3694911af140d22854543d4ae2b5f9e709b479"
65
  },
 
 
 
 
 
 
 
 
 
 
66
  {
67
  "path": "reports/p_boundary_device_stress_sharedfix_3seed.json",
68
  "bytes": 10867,
@@ -73,11 +83,6 @@
73
  "bytes": 16685,
74
  "sha256": "9d250e5c75d4f104971551c07a702810bf94fb5b6e5e587035a624933766356e"
75
  },
76
- {
77
- "path": "reports/online_casecontext_seed47.json",
78
- "bytes": 33727,
79
- "sha256": "c3dfd328d9ff0a55eed2cb74657ad87e5e164968fddd7fae8c8fd92e137a4557"
80
- },
81
  {
82
  "path": "src/math_ink_06.py",
83
  "bytes": 54708,
@@ -93,6 +98,11 @@
93
  "bytes": 18055,
94
  "sha256": "6fa378ccb7d08f605d4976b6ae08247d0b1fa3f2cb7ce00ba5d35b79c6dfbb47"
95
  },
 
 
 
 
 
96
  {
97
  "path": "src/tray_joint.py",
98
  "bytes": 19404,
@@ -108,25 +118,30 @@
108
  "bytes": 13772,
109
  "sha256": "8cc2dc1e13b56c21d53a76b9b863cdf5c8f8dd315da6eb18c1bd2b5b87c1a616"
110
  },
111
- {
112
- "path": "scripts/train_math_ink_06_p_boundary_auxiliary.py",
113
- "bytes": 20688,
114
- "sha256": "70ca8a05dcbd48e79d812cd7ff44ee3d8479055f898143daa6d6ea7580b2973e"
115
- },
116
  {
117
  "path": "scripts/summarize_math_ink_06_p_boundary_joint.py",
118
  "bytes": 4580,
119
  "sha256": "c6ce78f521232bdb7e967b0c358232a72dd3f79747f9e32eb240d9bb10c6a422"
120
  },
 
 
 
 
 
121
  {
122
  "path": "scripts/export_math_ink_06_litert.py",
123
  "bytes": 8637,
124
  "sha256": "e96b30ded57d33d4505b065c1ac69c5ac7db43618c0eb7f3b7fb787b6fcaf1f6"
125
  },
126
  {
127
- "path": "scripts/evaluate_math_ink_06_p_boundary_device_stress.py",
128
- "bytes": 10444,
129
- "sha256": "bdd75047c4887a6e53720f1c84d224545844cdbd9b0239826a605d578b3c92a6"
 
 
 
 
 
130
  },
131
  {
132
  "path": "scripts/train_math_ink_06_boundary_behavior_guard.py",
@@ -138,21 +153,6 @@
138
  "bytes": 9063,
139
  "sha256": "28cfc7b9b695256cfa9199d912d1d938d402292b88e9411d42fddb3508446d3b"
140
  },
141
- {
142
- "path": "scripts/sweep_math_ink_06_component_competition_guard.py",
143
- "bytes": 9084,
144
- "sha256": "e2dee616e2c6ebdc32281624889017685648b7076515242e04a1452d98d1c7da"
145
- },
146
- {
147
- "path": "reports/local_baseline_overmerge_audit.json",
148
- "bytes": 1237409,
149
- "sha256": "33a9ccafebd559ca8b173f011e9a0a6f495d37b8fdb2693673663479d3457071"
150
- },
151
- {
152
- "path": "exports/seed17/raster.pt2",
153
- "bytes": 9465689,
154
- "sha256": "419301d67bbfe7b807e1ea676a33827c749f632300392d54eaf48c701ca07512"
155
- },
156
  {
157
  "path": "exports/seed17/online.pt2",
158
  "bytes": 9192090,
@@ -163,6 +163,16 @@
163
  "bytes": 1030,
164
  "sha256": "48a224d03fb2e8f1c4fcb6ca3f61456521f4437b4cfc845572111cd84cb93833"
165
  },
 
 
 
 
 
 
 
 
 
 
166
  {
167
  "path": "models/seed17/online_adapter.pt",
168
  "bytes": 2875654,
@@ -178,11 +188,6 @@
178
  "bytes": 8638290,
179
  "sha256": "f3b0e53b50e41cf57d4881c501371b35648cf049d603984a0edf6148c2b62bd7"
180
  },
181
- {
182
- "path": "assets/stroke_encoding.svg",
183
- "bytes": 3882,
184
- "sha256": "66bf7659c2e86fd53e6583e7c5deb8d371432469c07d4e4ca0dd165b4a81f4ed"
185
- },
186
  {
187
  "path": "pyproject.snapshot.toml",
188
  "bytes": 669,
@@ -198,6 +203,16 @@
198
  "bytes": 2406,
199
  "sha256": "2419245ba889772d562d524999e9d14f801e70d87ce75e38231722eb5aecd697"
200
  },
 
 
 
 
 
 
 
 
 
 
201
  {
202
  "path": "assets/architecture.svg",
203
  "bytes": 5695,
@@ -208,11 +223,6 @@
208
  "bytes": 824191,
209
  "sha256": "18aff472c1bdb25a519b1553364229c9869aed1f36a9d663cf88a1bc808fab8f"
210
  },
211
- {
212
- "path": "README.md",
213
- "bytes": 11132,
214
- "sha256": "5d08c5e2735e52acb557ef6b7792f5573508508297ca8054ca5ecad2e7311d8d"
215
- },
216
  {
217
  "path": "reports/behavior_role_seed47.json",
218
  "bytes": 30091,
@@ -228,6 +238,16 @@
228
  "bytes": 29047,
229
  "sha256": "e2072fec1b1065777f0e9218c48d27f096b22f5545e7cc8d9962939282719561"
230
  },
 
 
 
 
 
 
 
 
 
 
231
  {
232
  "path": "reports/local_baseline_guard_report.json",
233
  "bytes": 24052,
@@ -238,16 +258,6 @@
238
  "bytes": 22284,
239
  "sha256": "4d3db5f71e5008381dd072f2c10aafb22e08f96e23f2a32f82a3a46abd9c70b9"
240
  },
241
- {
242
- "path": "reports/boundary_behavior_guard_report.json",
243
- "bytes": 72053,
244
- "sha256": "f55a230a9f0892b9676c71db46e9e527862b3d8da776dc43db767ce7a0f6a5c7"
245
- },
246
- {
247
- "path": "reports/behavior_role_3seed_summary.json",
248
- "bytes": 3567,
249
- "sha256": "b16049218d2d006d952f59f55642fa9f3fbfbc3cc3a730fbd7b075f507c3b251"
250
- },
251
  {
252
  "path": "models/seed31/online_adapter.pt",
253
  "bytes": 2875654,
@@ -263,6 +273,16 @@
263
  "bytes": 8638290,
264
  "sha256": "e3c57bc8cbbd4542cacf7ab9200a9031dcdc5ee63ffbd6ad6c9f7ef4f0a64f37"
265
  },
 
 
 
 
 
 
 
 
 
 
266
  {
267
  "path": "models/seed47/online_adapter.pt",
268
  "bytes": 2876038,
@@ -272,11 +292,6 @@
272
  "path": "models/seed47/behavior_role_head.pt",
273
  "bytes": 75794,
274
  "sha256": "f28fad4e0289e3bc9400829f41aba9bbd75c43d445b7462a84aadbdbe635c10b"
275
- },
276
- {
277
- "path": "models/seed47/base_378.pt",
278
- "bytes": 8638290,
279
- "sha256": "4131b21f6b00471c1c5a82aee4a2da45e599e42dc742fc1dd0dd8afb970f8939"
280
  }
281
  ]
282
  }
 
1
  ๏ปฟ{
2
+ "schema": "aiflow-hf-research-snapshot-v8",
3
+ "generated_at": "2026-07-23T20:04:13.5124140Z",
4
  "track": "R_noncommercial_plus_rejected_P_proxy",
5
  "product_validation": false,
6
  "public_release": true,
7
  "contains_raw_dataset": false,
8
+ "tests": "282 passed",
9
  "retracted_paths": [
10
  "models/auxiliary/boundary_auxiliary_head.pt",
11
  "models/auxiliary/seed17/boundary_joint_delta.pt",
 
28
  "bytes": 6803,
29
  "sha256": "4f842852093ca46b1942c942fd5e475ca6c19f044ba9e27b6d372f1aed56056e"
30
  },
31
+ {
32
+ "path": "reports/RESEARCH_REPORT.md",
33
+ "bytes": 33159,
34
+ "sha256": "19c06349b4316cb538a48fbe1cf5fccaaa386ca215615ae6ca53bfaefc0995df"
35
+ },
36
+ {
37
+ "path": "scripts/evaluate_math_ink_06_p_boundary_device_stress.py",
38
+ "bytes": 10444,
39
+ "sha256": "bdd75047c4887a6e53720f1c84d224545844cdbd9b0239826a605d578b3c92a6"
40
+ },
41
  {
42
  "path": "scripts/evaluate_crohme_tray_joint_selector.py",
43
  "bytes": 11671,
 
48
  "bytes": 11900,
49
  "sha256": "f32a18c8e7d3a0ea36379293e6be88bfb509b7df99846c38149fb8458e6cc994"
50
  },
 
 
 
 
 
 
 
 
 
 
51
  {
52
  "path": "reports/online_casecontext_seed31.json",
53
  "bytes": 33576,
 
63
  "bytes": 15740,
64
  "sha256": "27b31da71b9f39f7ded38aa1ce3694911af140d22854543d4ae2b5f9e709b479"
65
  },
66
+ {
67
+ "path": "reports/online_casecontext_seed47.json",
68
+ "bytes": 33727,
69
+ "sha256": "c3dfd328d9ff0a55eed2cb74657ad87e5e164968fddd7fae8c8fd92e137a4557"
70
+ },
71
+ {
72
+ "path": "reports/p_boundary_joint_seed17.json",
73
+ "bytes": 6920,
74
+ "sha256": "7af3bb995041e5ea621d3c9535f3552e264860f12a7e6145637849f5cd0220a8"
75
+ },
76
  {
77
  "path": "reports/p_boundary_device_stress_sharedfix_3seed.json",
78
  "bytes": 10867,
 
83
  "bytes": 16685,
84
  "sha256": "9d250e5c75d4f104971551c07a702810bf94fb5b6e5e587035a624933766356e"
85
  },
 
 
 
 
 
86
  {
87
  "path": "src/math_ink_06.py",
88
  "bytes": 54708,
 
98
  "bytes": 18055,
99
  "sha256": "6fa378ccb7d08f605d4976b6ae08247d0b1fa3f2cb7ce00ba5d35b79c6dfbb47"
100
  },
101
+ {
102
+ "path": "src/p_formula_gate06.py",
103
+ "bytes": 7910,
104
+ "sha256": "00c8cb3fd5b53f2d118886d7333fe75d62f2d7b7e7b161b662adbd43d1b14a7f"
105
+ },
106
  {
107
  "path": "src/tray_joint.py",
108
  "bytes": 19404,
 
118
  "bytes": 13772,
119
  "sha256": "8cc2dc1e13b56c21d53a76b9b863cdf5c8f8dd315da6eb18c1bd2b5b87c1a616"
120
  },
 
 
 
 
 
121
  {
122
  "path": "scripts/summarize_math_ink_06_p_boundary_joint.py",
123
  "bytes": 4580,
124
  "sha256": "c6ce78f521232bdb7e967b0c358232a72dd3f79747f9e32eb240d9bb10c6a422"
125
  },
126
+ {
127
+ "path": "scripts/preflight_math_ink_06_p_formula.py",
128
+ "bytes": 1664,
129
+ "sha256": "36aeeab2f2474ce874ef932b24eb062dfc3b9e6cf3c0d59410a052a9c9835a07"
130
+ },
131
  {
132
  "path": "scripts/export_math_ink_06_litert.py",
133
  "bytes": 8637,
134
  "sha256": "e96b30ded57d33d4505b065c1ac69c5ac7db43618c0eb7f3b7fb787b6fcaf1f6"
135
  },
136
  {
137
+ "path": "scripts/sweep_math_ink_06_component_competition_guard.py",
138
+ "bytes": 9084,
139
+ "sha256": "e2dee616e2c6ebdc32281624889017685648b7076515242e04a1452d98d1c7da"
140
+ },
141
+ {
142
+ "path": "scripts/train_math_ink_06_p_boundary_auxiliary.py",
143
+ "bytes": 20688,
144
+ "sha256": "70ca8a05dcbd48e79d812cd7ff44ee3d8479055f898143daa6d6ea7580b2973e"
145
  },
146
  {
147
  "path": "scripts/train_math_ink_06_boundary_behavior_guard.py",
 
153
  "bytes": 9063,
154
  "sha256": "28cfc7b9b695256cfa9199d912d1d938d402292b88e9411d42fddb3508446d3b"
155
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  {
157
  "path": "exports/seed17/online.pt2",
158
  "bytes": 9192090,
 
163
  "bytes": 1030,
164
  "sha256": "48a224d03fb2e8f1c4fcb6ca3f61456521f4437b4cfc845572111cd84cb93833"
165
  },
166
+ {
167
+ "path": "contracts/aiflow_p_formula_v1.schema.json",
168
+ "bytes": 1903,
169
+ "sha256": "c78c8a612d2f24a5c09fe1aa158b365481102869c3f84b3a5510a895b416c424"
170
+ },
171
+ {
172
+ "path": "exports/seed17/raster.pt2",
173
+ "bytes": 9465689,
174
+ "sha256": "419301d67bbfe7b807e1ea676a33827c749f632300392d54eaf48c701ca07512"
175
+ },
176
  {
177
  "path": "models/seed17/online_adapter.pt",
178
  "bytes": 2875654,
 
188
  "bytes": 8638290,
189
  "sha256": "f3b0e53b50e41cf57d4881c501371b35648cf049d603984a0edf6148c2b62bd7"
190
  },
 
 
 
 
 
191
  {
192
  "path": "pyproject.snapshot.toml",
193
  "bytes": 669,
 
203
  "bytes": 2406,
204
  "sha256": "2419245ba889772d562d524999e9d14f801e70d87ce75e38231722eb5aecd697"
205
  },
206
+ {
207
+ "path": "README.md",
208
+ "bytes": 11248,
209
+ "sha256": "d102514283972dbddc061848a1fb33a5d4f581dea0b43dc9eb3f4f8de46d5885"
210
+ },
211
+ {
212
+ "path": "assets/stroke_encoding.svg",
213
+ "bytes": 3882,
214
+ "sha256": "66bf7659c2e86fd53e6583e7c5deb8d371432469c07d4e4ca0dd165b4a81f4ed"
215
+ },
216
  {
217
  "path": "assets/architecture.svg",
218
  "bytes": 5695,
 
223
  "bytes": 824191,
224
  "sha256": "18aff472c1bdb25a519b1553364229c9869aed1f36a9d663cf88a1bc808fab8f"
225
  },
 
 
 
 
 
226
  {
227
  "path": "reports/behavior_role_seed47.json",
228
  "bytes": 30091,
 
238
  "bytes": 29047,
239
  "sha256": "e2072fec1b1065777f0e9218c48d27f096b22f5545e7cc8d9962939282719561"
240
  },
241
+ {
242
+ "path": "reports/boundary_behavior_guard_report.json",
243
+ "bytes": 72053,
244
+ "sha256": "f55a230a9f0892b9676c71db46e9e527862b3d8da776dc43db767ce7a0f6a5c7"
245
+ },
246
+ {
247
+ "path": "reports/local_baseline_overmerge_audit.json",
248
+ "bytes": 1237409,
249
+ "sha256": "33a9ccafebd559ca8b173f011e9a0a6f495d37b8fdb2693673663479d3457071"
250
+ },
251
  {
252
  "path": "reports/local_baseline_guard_report.json",
253
  "bytes": 24052,
 
258
  "bytes": 22284,
259
  "sha256": "4d3db5f71e5008381dd072f2c10aafb22e08f96e23f2a32f82a3a46abd9c70b9"
260
  },
 
 
 
 
 
 
 
 
 
 
261
  {
262
  "path": "models/seed31/online_adapter.pt",
263
  "bytes": 2875654,
 
273
  "bytes": 8638290,
274
  "sha256": "e3c57bc8cbbd4542cacf7ab9200a9031dcdc5ee63ffbd6ad6c9f7ef4f0a64f37"
275
  },
276
+ {
277
+ "path": "models/seed47/base_378.pt",
278
+ "bytes": 8638290,
279
+ "sha256": "4131b21f6b00471c1c5a82aee4a2da45e599e42dc742fc1dd0dd8afb970f8939"
280
+ },
281
+ {
282
+ "path": "reports/behavior_role_3seed_summary.json",
283
+ "bytes": 3567,
284
+ "sha256": "b16049218d2d006d952f59f55642fa9f3fbfbc3cc3a730fbd7b075f507c3b251"
285
+ },
286
  {
287
  "path": "models/seed47/online_adapter.pt",
288
  "bytes": 2876038,
 
292
  "path": "models/seed47/behavior_role_head.pt",
293
  "bytes": 75794,
294
  "sha256": "f28fad4e0289e3bc9400829f41aba9bbd75c43d445b7462a84aadbdbe635c10b"
 
 
 
 
 
295
  }
296
  ]
297
  }
README.md CHANGED
@@ -247,4 +247,5 @@ PyTorch checkpoint์™€ joblib/pickle์€ ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋Š” ์ถœ์ฒ˜์—์„œ ๋กœ๋“œ
247
  - P boundary ์ •์ • 3-seed: [`reports/p_boundary_joint_sharedfix_3seed_summary.json`](reports/p_boundary_joint_sharedfix_3seed_summary.json)
248
  - ์ •์ • main device stress: [`reports/p_boundary_device_stress_sharedfix_3seed.json`](reports/p_boundary_device_stress_sharedfix_3seed.json)
249
  - Seed-17 composite export: [`exports/seed17/export_manifest.json`](exports/seed17/export_manifest.json)
 
250
  - ํŒŒ์ผ checksum: [`MANIFEST.json`](MANIFEST.json)
 
247
  - P boundary ์ •์ • 3-seed: [`reports/p_boundary_joint_sharedfix_3seed_summary.json`](reports/p_boundary_joint_sharedfix_3seed_summary.json)
248
  - ์ •์ • main device stress: [`reports/p_boundary_device_stress_sharedfix_3seed.json`](reports/p_boundary_device_stress_sharedfix_3seed.json)
249
  - Seed-17 composite export: [`exports/seed17/export_manifest.json`](exports/seed17/export_manifest.json)
250
+ - ์‹ค์ œ P formula schema: [`contracts/aiflow_p_formula_v1.schema.json`](contracts/aiflow_p_formula_v1.schema.json)
251
  - ํŒŒ์ผ checksum: [`MANIFEST.json`](MANIFEST.json)
contracts/aiflow_p_formula_v1.schema.json ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://aiflow.local/schemas/p-formula-v1.json",
4
+ "title": "AIFlow Math Ink 0.6 P Formula Record",
5
+ "type": "object",
6
+ "required": [
7
+ "formula_id",
8
+ "origin_id",
9
+ "writer_id",
10
+ "device_id",
11
+ "source_id",
12
+ "split",
13
+ "canvas_width",
14
+ "canvas_height",
15
+ "rights_track",
16
+ "commercial_training_allowed",
17
+ "symbols"
18
+ ],
19
+ "properties": {
20
+ "formula_id": {"type": "string", "minLength": 1},
21
+ "origin_id": {"type": "string", "minLength": 1},
22
+ "writer_id": {"type": "string", "minLength": 1},
23
+ "device_id": {"type": "string", "minLength": 1},
24
+ "source_id": {"type": "string", "minLength": 1},
25
+ "split": {"enum": ["training", "validation", "test"]},
26
+ "canvas_width": {"type": "number", "exclusiveMinimum": 0},
27
+ "canvas_height": {"type": "number", "exclusiveMinimum": 0},
28
+ "rights_track": {"const": "P"},
29
+ "commercial_training_allowed": {"const": true},
30
+ "symbols": {
31
+ "type": "array",
32
+ "minItems": 1,
33
+ "items": {
34
+ "type": "object",
35
+ "required": ["token", "strokes"],
36
+ "properties": {
37
+ "token": {"type": "string", "minLength": 1},
38
+ "strokes": {
39
+ "type": "array",
40
+ "minItems": 1,
41
+ "items": {
42
+ "type": "array",
43
+ "minItems": 1,
44
+ "items": {
45
+ "type": "object",
46
+ "required": ["x", "y"],
47
+ "properties": {
48
+ "x": {"type": "number"},
49
+ "y": {"type": "number"},
50
+ "t": {"type": ["number", "null"]},
51
+ "pressure": {"type": ["number", "null"]}
52
+ },
53
+ "additionalProperties": true
54
+ }
55
+ }
56
+ }
57
+ },
58
+ "additionalProperties": true
59
+ }
60
+ }
61
+ },
62
+ "additionalProperties": true
63
+ }
reports/RESEARCH_REPORT.md CHANGED
@@ -409,6 +409,19 @@ Joint delta ์—†์ด ์ •์ •๋œ main๊ณผ ์ƒˆ auxiliary head๋งŒ ๋Œ€์ƒ์œผ๋กœ device s
409
 
410
  Seed 17ยท31ยท47 ๋ชจ๋‘ online/raster ๊ฐ๊ฐ ๋Œ€ํ‘œ ์ž…๋ ฅ 76๊ฐœ์—์„œ eager ๋Œ€๋น„ top-1 100% ์ผ์น˜, ์ตœ๋Œ€ logit ์ ˆ๋Œ€์˜ค์ฐจ 0.0์œผ๋กœ strict `torch.export` gate๋ฅผ ํ†ต๊ณผํ–ˆ๋‹ค. Seed๋‹น ๋‘ graph ํ•ฉ๊ณ„๋Š” 18,657,779 bytes๋กœ 25MB ์˜ˆ์‚ฐ ์•ˆ์ด๋‹ค. ๋‹ค๋งŒ `.pt2`๋Š” Android LiteRT artifact๊ฐ€ ์•„๋‹ˆ๋‹ค. ๊ณต์‹ LiteRT Torch 0.9.1์€ Linux ํ™˜๊ฒฝ์„ ์š”๊ตฌํ•˜๋ฉฐ WSL ๋ณ€ํ™˜ ํ™˜๊ฒฝ ์„ค์น˜ ์ค‘ WSL filesystem I/O ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ด `.tflite` ๋ณ€ํ™˜๊ณผ runtime parity๋Š” ์•„์ง ๋ฏธ์™„๋ฃŒ๋‹ค.
411
 
 
 
 
 
 
 
 
 
 
 
 
 
 
412
  ## ์‚ฐ์ถœ๋ฌผ
413
 
414
  - `src/math_grid_drawer/research/behavior_context06.py`
@@ -432,9 +445,12 @@ Seed 17ยท31ยท47 ๋ชจ๋‘ online/raster ๊ฐ๊ฐ ๋Œ€ํ‘œ ์ž…๋ ฅ 76๊ฐœ์—์„œ eager ๋Œ€
432
  - `scripts/summarize_math_ink_06_p_boundary_joint.py`
433
  - `scripts/evaluate_math_ink_06_p_boundary_device_stress.py`
434
  - `scripts/export_math_ink_06_litert.py`
 
435
  - `scripts/analyze_crohme_lattice_failures.py`
436
  - `tests/test_behavior_context06.py`
437
  - `tests/test_behavior_role_head06.py`
 
 
438
  - `research/AIFlow-MATH-INK-0.6-BEHAVIOR-CONTEXT-REPORT-20260724.md`
439
  - `research/runs/math_ink_06_behavior_role_3seed_20260724/run_summary.json`
440
  - `research/runs/math_ink_06_behavior_grouping_audit_20260724/report.json`
 
409
 
410
  Seed 17ยท31ยท47 ๋ชจ๋‘ online/raster ๊ฐ๊ฐ ๋Œ€ํ‘œ ์ž…๋ ฅ 76๊ฐœ์—์„œ eager ๋Œ€๋น„ top-1 100% ์ผ์น˜, ์ตœ๋Œ€ logit ์ ˆ๋Œ€์˜ค์ฐจ 0.0์œผ๋กœ strict `torch.export` gate๋ฅผ ํ†ต๊ณผํ–ˆ๋‹ค. Seed๋‹น ๋‘ graph ํ•ฉ๊ณ„๋Š” 18,657,779 bytes๋กœ 25MB ์˜ˆ์‚ฐ ์•ˆ์ด๋‹ค. ๋‹ค๋งŒ `.pt2`๋Š” Android LiteRT artifact๊ฐ€ ์•„๋‹ˆ๋‹ค. ๊ณต์‹ LiteRT Torch 0.9.1์€ Linux ํ™˜๊ฒฝ์„ ์š”๊ตฌํ•˜๋ฉฐ WSL ๋ณ€ํ™˜ ํ™˜๊ฒฝ ์„ค์น˜ ์ค‘ WSL filesystem I/O ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ด `.tflite` ๋ณ€ํ™˜๊ณผ runtime parity๋Š” ์•„์ง ๋ฏธ์™„๋ฃŒ๋‹ค.
411
 
412
+ ### ์‹ค์ œ P ์—ฐ์†์‹ ๋ฐ์ดํ„ฐ ๊ณ„์•ฝ
413
+
414
+ ์‹ค์ œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋„์ฐฉํ•˜๊ธฐ ์ „์— `AIFlow P Formula v1` JSON Schema์™€ fail-closed preflight๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋‹ค. ๊ฐ formula๋Š” ๋‹ค์Œ ๊ทผ๊ฑฐ๋ฅผ ๋ชจ๋‘ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค.
415
+
416
+ - ๊ณ ์œ  `formula_id`, ์›๋ณธ ์ถ”์ ์šฉ `origin_id`
417
+ - ๋น„์–ด ์žˆ์ง€ ์•Š์€ `writer_id`, `device_id`, `source_id`
418
+ - `training|validation|test` split
419
+ - `rights_track=P`, `commercial_training_allowed=true`
420
+ - ์–‘์ˆ˜ canvas ํฌ๊ธฐ
421
+ - token๊ณผ ์›๋ณธ raw stroke๊ฐ€ ํฌํ•จ๋œ ์ •๋‹ต symbol group
422
+
423
+ Originยทwriterยทdeviceยทsource๊ฐ€ ๋‘˜ ์ด์ƒ์˜ split์— ๋‚˜ํƒ€๋‚˜๋ฉด ์ œํ’ˆ ํ‰๊ฐ€๋ฅผ ๊ฑฐ๋ถ€ํ•œ๋‹ค. Timestamp์™€ pressure๊ฐ€ ์—†๋Š” symbol์€ ์‚ญ์ œํ•˜๊ฑฐ๋‚˜ ๊ด€์ธก๊ฐ’์œผ๋กœ ์œ„์žฅํ•˜์ง€ ์•Š๊ณ  missing slice๋กœ ์„ผ๋‹ค. ๊ฒ€์ฆ๋œ formula์˜ ์‹ค์ œ symbol group์€ boundary ์Œ์„ฑ, ์ธ์ ‘ํ•œ ๋‘ symbol group ๊ฒฐํ•ฉ์€ boundary ์–‘์„ฑ์œผ๋กœ ๋งŒ๋“ ๋‹ค. ์ด ๊ณ„์•ฝ์€ ์‹ค์ œ ์„ฑ๋Šฅ๊ฐ’์„ ๋งŒ๋“ค์ง€๋Š” ์•Š์ง€๋งŒ, ํ–ฅํ›„ P ์ž…๋ ฅ์ด CROHME ์ •๋‹ต group์ด๋‚˜ ํ•ฉ์„ฑ ๊ณ ๋ฆฝ๊ธฐํ˜ธ proxy์™€ ์„ž์ด๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•œ๋‹ค. ์ „์ฒด ํšŒ๊ท€๋Š” 282๊ฐœ๊ฐ€ ํ†ต๊ณผํ–ˆ๋‹ค.
424
+
425
  ## ์‚ฐ์ถœ๋ฌผ
426
 
427
  - `src/math_grid_drawer/research/behavior_context06.py`
 
445
  - `scripts/summarize_math_ink_06_p_boundary_joint.py`
446
  - `scripts/evaluate_math_ink_06_p_boundary_device_stress.py`
447
  - `scripts/export_math_ink_06_litert.py`
448
+ - `scripts/preflight_math_ink_06_p_formula.py`
449
  - `scripts/analyze_crohme_lattice_failures.py`
450
  - `tests/test_behavior_context06.py`
451
  - `tests/test_behavior_role_head06.py`
452
+ - `tests/test_p_formula_gate06.py`
453
+ - `research/contracts/aiflow_p_formula_v1.schema.json`
454
  - `research/AIFlow-MATH-INK-0.6-BEHAVIOR-CONTEXT-REPORT-20260724.md`
455
  - `research/runs/math_ink_06_behavior_role_3seed_20260724/run_summary.json`
456
  - `research/runs/math_ink_06_behavior_grouping_audit_20260724/report.json`
scripts/preflight_math_ink_06_p_formula.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """์‹ค์ œ P ์—ฐ์† ์ˆ˜์‹ JSONL์„ ํ•™์Šตยทํ‰๊ฐ€ ์ „์— fail-closed๋กœ ๊ฐ์‚ฌํ•œ๋‹ค."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ from datetime import datetime, timezone
7
+ import json
8
+ from pathlib import Path
9
+ import sys
10
+
11
+ PROJECT_ROOT = Path(__file__).parents[1]
12
+ SOURCE_ROOT = PROJECT_ROOT / "src"
13
+ if str(SOURCE_ROOT) not in sys.path:
14
+ sys.path.insert(0, str(SOURCE_ROOT))
15
+
16
+ from math_grid_drawer.research.external_corpus import read_jsonl
17
+ from math_grid_drawer.research.p_formula_gate06 import audit_p_formula_records06
18
+
19
+
20
+ def main() -> None:
21
+ """ํ•„์š” ๋ณ€์ˆ˜: UTF-8 JSONLยท์ตœ์†Œ source ์ˆ˜ยท์ถœ๋ ฅ. ์ž‘๋™ ์›๋ฆฌ: ์‹ค์ œ P gate ์ ๊ฒฉ ์—ฌ๋ถ€์™€ ๋ชจ๋“  ๋ˆ„์ˆ˜ ์›์ธ์„ JSON์œผ๋กœ ๋‚จ๊ธด๋‹ค."""
22
+
23
+ parser = argparse.ArgumentParser(description="Preflight real P continuous formula data")
24
+ parser.add_argument("--data", type=Path, required=True)
25
+ parser.add_argument("--minimum-independent-sources", type=int, default=2)
26
+ parser.add_argument("--output", type=Path, required=True)
27
+ args = parser.parse_args()
28
+ records = list(read_jsonl(args.data))
29
+ report = audit_p_formula_records06(
30
+ records, minimum_independent_sources=args.minimum_independent_sources,
31
+ )
32
+ report["generated_at"] = datetime.now(timezone.utc).isoformat()
33
+ report["data"] = str(args.data)
34
+ args.output.parent.mkdir(parents=True, exist_ok=True)
35
+ args.output.write_text(
36
+ json.dumps(report, ensure_ascii=False, indent=2) + "\n", encoding="utf-8",
37
+ )
38
+ print(json.dumps(report, ensure_ascii=False, indent=2))
39
+ if not report["eligible_for_product_evaluation"]:
40
+ raise SystemExit(2)
41
+
42
+
43
+ if __name__ == "__main__":
44
+ main()
src/p_formula_gate06.py ADDED
@@ -0,0 +1,186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """์‹ค์ œ P ์—ฐ์† ์ˆ˜์‹์˜ ๊ถŒ๋ฆฌยท๋ถ„ํ• ยทsymbol-group ๊ณ„์•ฝ์„ fail-closed๋กœ ๊ฒ€์‚ฌํ•œ๋‹ค."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections import defaultdict
6
+ from collections.abc import Iterable, Sequence
7
+ from typing import Any
8
+
9
+
10
+ REQUIRED_SPLITS_06 = frozenset({"training", "validation", "test"})
11
+ REQUIRED_RECORD_FIELDS_06 = (
12
+ "formula_id", "origin_id", "writer_id", "device_id", "source_id", "split",
13
+ "canvas_width", "canvas_height", "symbols", "rights_track",
14
+ "commercial_training_allowed",
15
+ )
16
+
17
+
18
+ def _identity_overlap06(records: Sequence[dict[str, Any]], field: str) -> dict[str, list[str]]:
19
+ """ํ•„์š” ๋ณ€์ˆ˜: formula recordยทidentity field. ์ž‘๋™ ์›๋ฆฌ: ํ•˜๋‚˜์˜ identity๊ฐ€ ๋‘˜ ์ด์ƒ์˜ split์— ๋‚˜ํƒ€๋‚œ ๊ฒฝ์šฐ๋งŒ ๋ฐ˜ํ™˜ํ•œ๋‹ค."""
20
+
21
+ split_by_identity: dict[str, set[str]] = defaultdict(set)
22
+ for record in records:
23
+ value = str(record.get(field) or "").strip()
24
+ if value:
25
+ split_by_identity[value].add(str(record.get("split") or ""))
26
+ return {
27
+ identity: sorted(splits)
28
+ for identity, splits in split_by_identity.items()
29
+ if len(splits) > 1
30
+ }
31
+
32
+
33
+ def _valid_strokes06(strokes: Any) -> bool:
34
+ """ํ•„์š” ๋ณ€์ˆ˜: symbol stroke payload. ์ž‘๋™ ์›๋ฆฌ: ๋น„์–ด ์žˆ์ง€ ์•Š์€ ํš๊ณผ ์œ ํ•œ ์ขŒํ‘œ ํ•„๋“œ๋ฅผ ๊ตฌ์กฐ์ ์œผ๋กœ ๊ฒ€์‚ฌํ•œ๋‹ค."""
35
+
36
+ if not isinstance(strokes, list) or not strokes:
37
+ return False
38
+ for stroke in strokes:
39
+ if not isinstance(stroke, list) or not stroke:
40
+ return False
41
+ for point in stroke:
42
+ if not isinstance(point, dict) or "x" not in point or "y" not in point:
43
+ return False
44
+ try:
45
+ x, y = float(point["x"]), float(point["y"])
46
+ except (TypeError, ValueError):
47
+ return False
48
+ if not (-1e9 < x < 1e9 and -1e9 < y < 1e9):
49
+ return False
50
+ return True
51
+
52
+
53
+ def audit_p_formula_records06(
54
+ records: Sequence[dict[str, Any]], *, minimum_independent_sources: int = 2,
55
+ ) -> dict[str, Any]:
56
+ """ํ•„์š” ๋ณ€์ˆ˜: ์‹ค์ œ ์—ฐ์†์‹ record. ์ž‘๋™ ์›๋ฆฌ: P ๊ถŒ๋ฆฌยทํ•„์ˆ˜ metadataยทidentity ๋ˆ„์ˆ˜ยทgroup ์ •๋‹ต์„ ํ•œ ๋ฒˆ์— ๊ฐ์‚ฌํ•œ๋‹ค."""
57
+
58
+ issues: list[dict[str, Any]] = []
59
+ formula_ids: set[str] = set()
60
+ origin_splits: dict[str, set[str]] = defaultdict(set)
61
+ split_counts: dict[str, int] = defaultdict(int)
62
+ symbol_counts: dict[str, int] = defaultdict(int)
63
+ missing_timestamp_symbols = missing_pressure_symbols = total_symbols = 0
64
+
65
+ for index, record in enumerate(records):
66
+ missing = [
67
+ field for field in REQUIRED_RECORD_FIELDS_06
68
+ if field not in record or record[field] is None or record[field] == ""
69
+ ]
70
+ if missing:
71
+ issues.append({"type": "missing_fields", "record_index": index, "fields": missing})
72
+ continue
73
+ formula_id = str(record["formula_id"])
74
+ if formula_id in formula_ids:
75
+ issues.append({"type": "duplicate_formula_id", "formula_id": formula_id})
76
+ formula_ids.add(formula_id)
77
+ split = str(record["split"])
78
+ split_counts[split] += 1
79
+ if split not in REQUIRED_SPLITS_06:
80
+ issues.append({"type": "invalid_split", "formula_id": formula_id, "split": split})
81
+ origin_splits[str(record["origin_id"])].add(split)
82
+ if str(record["rights_track"]) != "P" or record["commercial_training_allowed"] is not True:
83
+ issues.append({"type": "rights_not_product_approved", "formula_id": formula_id})
84
+ try:
85
+ if float(record["canvas_width"]) <= 0 or float(record["canvas_height"]) <= 0:
86
+ raise ValueError
87
+ except (TypeError, ValueError):
88
+ issues.append({"type": "invalid_canvas", "formula_id": formula_id})
89
+
90
+ symbols = record["symbols"]
91
+ if not isinstance(symbols, list) or not symbols:
92
+ issues.append({"type": "empty_symbol_groups", "formula_id": formula_id})
93
+ continue
94
+ for symbol_index, symbol in enumerate(symbols):
95
+ total_symbols += 1
96
+ token = str(symbol.get("token") or "").strip() if isinstance(symbol, dict) else ""
97
+ if not token or not isinstance(symbol, dict) or not _valid_strokes06(symbol.get("strokes")):
98
+ issues.append({
99
+ "type": "invalid_symbol_group", "formula_id": formula_id,
100
+ "symbol_index": symbol_index,
101
+ })
102
+ continue
103
+ symbol_counts[token] += 1
104
+ points = [point for stroke in symbol["strokes"] for point in stroke]
105
+ if not all(point.get("t") is not None for point in points):
106
+ missing_timestamp_symbols += 1
107
+ if not all(point.get("pressure") is not None for point in points):
108
+ missing_pressure_symbols += 1
109
+
110
+ for origin, splits in origin_splits.items():
111
+ if len(splits) > 1:
112
+ issues.append({"type": "origin_split_leakage", "origin_id": origin, "splits": sorted(splits)})
113
+ identity_overlap = {
114
+ field: _identity_overlap06(records, field)
115
+ for field in ("writer_id", "device_id", "source_id")
116
+ }
117
+ for field, overlaps in identity_overlap.items():
118
+ if overlaps:
119
+ issues.append({
120
+ "type": f"{field}_split_leakage",
121
+ "count": len(overlaps),
122
+ "examples": dict(list(overlaps.items())[:10]),
123
+ })
124
+ missing_splits = sorted(REQUIRED_SPLITS_06 - set(split_counts))
125
+ if missing_splits:
126
+ issues.append({"type": "missing_required_splits", "splits": missing_splits})
127
+ independent_sources = len({str(record.get("source_id") or "") for record in records if record.get("source_id")})
128
+ if independent_sources < minimum_independent_sources:
129
+ issues.append({
130
+ "type": "insufficient_independent_sources",
131
+ "observed": independent_sources, "required": minimum_independent_sources,
132
+ })
133
+
134
+ return {
135
+ "schema": "aiflow-p-formula-preflight-v1",
136
+ "records": len(records),
137
+ "symbols": total_symbols,
138
+ "split_counts": dict(sorted(split_counts.items())),
139
+ "label_count": len(symbol_counts),
140
+ "independent_sources": independent_sources,
141
+ "identity_overlap_counts": {
142
+ field: len(overlaps) for field, overlaps in identity_overlap.items()
143
+ },
144
+ "missing_metadata_slices": {
145
+ "timestamp_symbols": missing_timestamp_symbols,
146
+ "pressure_symbols": missing_pressure_symbols,
147
+ },
148
+ "issues": issues,
149
+ "eligible_for_product_evaluation": not issues,
150
+ "product_validation": False,
151
+ }
152
+
153
+
154
+ def formula_boundary_candidates06(record: dict[str, Any]) -> list[dict[str, Any]]:
155
+ """ํ•„์š” ๋ณ€์ˆ˜: ๊ฒ€์ฆ๋œ formula record. ์ž‘๋™ ์›๋ฆฌ: ์‹ค์ œ ๋‹จ์ผ group๊ณผ ์ธ์ ‘ ๋‘ group ๊ฒฐํ•ฉ์„ boundary ์ •๋‹ต ํ›„๋ณด๋กœ ๋งŒ๋“ ๋‹ค."""
156
+
157
+ symbols = record["symbols"]
158
+ candidates = [
159
+ {
160
+ "formula_id": str(record["formula_id"]),
161
+ "symbol_indices": [index],
162
+ "strokes": symbol["strokes"],
163
+ "boundary_target": 0,
164
+ }
165
+ for index, symbol in enumerate(symbols)
166
+ ]
167
+ for index in range(len(symbols) - 1):
168
+ candidates.append({
169
+ "formula_id": str(record["formula_id"]),
170
+ "symbol_indices": [index, index + 1],
171
+ "strokes": [*symbols[index]["strokes"], *symbols[index + 1]["strokes"]],
172
+ "boundary_target": 1,
173
+ })
174
+ return candidates
175
+
176
+
177
+ def collect_formula_boundary_candidates06(
178
+ records: Iterable[dict[str, Any]],
179
+ ) -> list[dict[str, Any]]:
180
+ """ํ•„์š” ๋ณ€์ˆ˜: ๊ฒ€์ฆ๋œ formula iterable. ์ž‘๋™ ์›๋ฆฌ: formula๋ณ„ ์‹ค์ œ group ํ›„๋ณด๋ฅผ ํ‰๊ฐ€์šฉ ํ‰ํƒ„ ๋ชฉ๋ก์œผ๋กœ ๋งŒ๋“ ๋‹ค."""
181
+
182
+ return [
183
+ candidate
184
+ for record in records
185
+ for candidate in formula_boundary_candidates06(record)
186
+ ]