File size: 36,332 Bytes
4eefabb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Progress-Update Brief — MicroClimate-X</title>
<style>
  /* ============================================================
     Print-optimised A4 progress-update brief
     Open in browser → ⌘+P → Save as PDF, or read on screen
     ============================================================ */
  :root {
    --ink:           #0b0d12;
    --ink-soft:      #353a44;
    --muted:         #6b7280;
    --brand:         #2563eb;
    --brand-soft:    #dbeafe;
    --accent:        #b91c1c;
    --accent-soft:   #fee2e2;
    --ok:            #166534;
    --ok-soft:       #dcfce7;
    --warn:          #b45309;
    --warn-soft:     #fef3c7;
    --grid:          #e5e7eb;
    --bg:            #ffffff;
    --code-bg:       #f3f4f6;
  }

  * { box-sizing: border-box; }
  html, body { margin: 0; padding: 0; background: var(--bg); color: var(--ink); }
  body {
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text",
                 "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
                 system-ui, sans-serif;
    font-size: 11pt;
    line-height: 1.45;
  }

  @page { size: A4; margin: 12mm 14mm; }
  main { max-width: 200mm; margin: 0 auto; padding: 14mm 14mm; }

  /* Headings */
  h1 {
    font-size: 22pt; margin: 0 0 4mm 0;
    border-bottom: 3px solid var(--brand); padding-bottom: 3mm;
    page-break-after: avoid;
  }
  h1 .zh { display: block; font-size: 13pt; color: var(--muted); font-weight: 500; margin-top: 1mm; }
  h2 {
    font-size: 14pt; margin: 9mm 0 3mm 0;
    color: var(--brand);
    border-left: 4px solid var(--brand); padding: 1mm 0 1mm 3mm;
    page-break-after: avoid;
  }
  h2 .zh { display: block; font-size: 10pt; color: var(--muted); margin-top: 0.5mm; font-weight: 500; }
  h3 {
    font-size: 11.5pt; margin: 5mm 0 2mm 0; color: var(--ink-soft);
    page-break-after: avoid;
  }
  h4 { font-size: 10.5pt; margin: 3mm 0 1mm 0; color: var(--accent); }

  p, li { margin: 1mm 0; }
  ul, ol { padding-left: 5mm; }
  ul li { margin-bottom: 1mm; }

  /* Quote / supervisor verbatim */
  .quote {
    background: var(--warn-soft);
    border-left: 3px solid var(--warn);
    padding: 2mm 3mm; margin: 2mm 0;
    font-style: italic; font-size: 10pt;
  }
  .quote::before { content: "🎙️ "; font-style: normal; }

  /* Tables */
  table.bilingual, table.steps, table.tabs, table.plan, table {
    border-collapse: collapse; width: 100%; margin: 2mm 0 3mm 0;
    font-size: 10pt;
  }
  table.bilingual td, table.steps td, table.tabs td, table.plan td,
  table th, table td {
    padding: 1.5mm 2.5mm; vertical-align: top;
    border: 1px solid var(--grid);
  }
  table th {
    background: #f9fafb; font-weight: 600; text-align: left;
    color: var(--ink-soft);
  }
  table.bilingual td.en { width: 50%; }
  table.bilingual td.zh { width: 50%; background: #fafbfc; }
  table.plan td.estimate { width: 14%; text-align: center; color: var(--brand); font-weight: 600; }

  /* Inline callouts */
  .callout {
    margin: 2mm 0; padding: 2mm 3mm;
    border-left: 3px solid; border-radius: 1mm;
    font-size: 10pt;
  }
  .callout.warn { background: var(--accent-soft); border-color: var(--accent); }
  .callout.ok   { background: var(--ok-soft); border-color: var(--ok); }
  .callout.tip  { background: var(--brand-soft); border-color: var(--brand); }
  .callout-title { font-weight: 700; margin-bottom: 1mm; }

  /* Code */
  code, pre, kbd {
    font-family: "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
    font-size: 9.5pt;
  }
  code { background: var(--code-bg); padding: 0.3mm 1mm; border-radius: 1mm; }
  pre {
    background: var(--code-bg); padding: 3mm; border-radius: 2mm;
    overflow-x: auto; margin: 2mm 0;
    border: 1px solid var(--grid);
  }
  pre code { background: transparent; padding: 0; }

  /* Step indicators */
  .step {
    display: flex; gap: 3mm;
    margin: 2mm 0;
    align-items: flex-start;
  }
  .step .num {
    flex: 0 0 8mm; width: 8mm; height: 8mm; border-radius: 50%;
    background: var(--brand); color: white; font-weight: 700;
    display: flex; align-items: center; justify-content: center;
    font-size: 11pt;
  }
  .step .body { flex: 1; }

  /* Demo / decision blocks */
  .demo {
    background: #f0f9ff;
    border: 1px solid #bae6fd;
    border-radius: 2mm;
    padding: 3mm;
    margin: 3mm 0;
  }
  .demo .demo-title { font-weight: 700; color: #075985; margin-bottom: 1mm; }

  .decision {
    background: #fefce8;
    border: 1px solid #fde047;
    border-radius: 2mm;
    padding: 3mm;
    margin: 2mm 0;
  }
  .decision .decision-title {
    font-weight: 700; color: #854d0e; margin-bottom: 1mm;
    text-transform: uppercase; letter-spacing: 0.5pt; font-size: 9pt;
  }

  /* Status pill */
  .pill {
    display: inline-block; padding: 0.2mm 1.5mm;
    border-radius: 4mm; font-size: 8.5pt; font-weight: 600;
    vertical-align: middle;
  }
  .pill.done { background: var(--ok-soft); color: var(--ok); }
  .pill.plan { background: var(--brand-soft); color: var(--brand); }
  .pill.risk { background: var(--accent-soft); color: var(--accent); }

  /* Checklist */
  .check { font-family: "SF Mono", Menlo, monospace; font-size: 9.5pt; line-height: 1.7; }
  .check .box { display: inline-block; width: 4mm; }

  /* Page break helpers */
  .pb { page-break-before: always; }
  .nobreak { page-break-inside: avoid; }

  /* Footer */
  footer {
    margin-top: 12mm; padding-top: 4mm;
    border-top: 1px solid var(--grid);
    color: var(--muted); font-size: 9pt; text-align: center;
  }

  /* Print refinements */
  @media print {
    body { font-size: 10pt; }
    h2 { font-size: 13pt; }
    .no-print { display: none; }
    a { color: var(--ink); text-decoration: none; }
  }

  /* Toolbar (screen only) */
  .toolbar {
    position: sticky; top: 0; z-index: 100;
    background: var(--brand); color: white;
    padding: 2mm 4mm; display: flex; justify-content: space-between;
    align-items: center; font-size: 10pt;
  }
  .toolbar button {
    background: white; color: var(--brand); border: 0;
    padding: 1.5mm 4mm; border-radius: 1mm; font-weight: 600;
    cursor: pointer; font-size: 10pt;
  }
  .toolbar button:hover { background: #f3f4f6; }

  /* Cover meta strip */
  .cover-meta {
    display: flex; gap: 4mm; flex-wrap: wrap;
    margin: 3mm 0;
    color: var(--muted); font-size: 9.5pt;
  }
  .cover-meta span {
    background: var(--code-bg); padding: 0.5mm 2mm; border-radius: 1mm;
  }

  /* Timeline strip in §0.2 */
  table.timeline td.block { width: 8%; text-align: center; font-weight: 700; color: var(--brand); }
  table.timeline td.time  { width: 18%; font-family: "SF Mono", Menlo, monospace; color: var(--muted); }
</style>
</head>
<body>

<div class="toolbar no-print">
  <strong>Progress-Update Brief · MicroClimate-X</strong>
  <button onclick="window.print()">🖨 Print / Save as PDF</button>
</div>

<main>

<h1>Supervisor Progress-Update Brief
  <span class="zh">导师进度汇报双语逐字稿 — MicroClimate-X</span>
</h1>

<div class="cover-meta">
  <span>📅 2026-05-13</span>
  <span>🎓 UKM FYP</span>
  <span>🏛️ KyoukoLi/microclimate-x</span>
  <span>🚀 v1.0.0 shipped 2026-05-11</span>
  <span>✅ 70 tests · 97% coverage</span>
</div>

<div class="callout tip">
  <div class="callout-title">How to use this brief · 怎么用这份汇报稿</div>
  Follow-up meeting after the v1.0.0 hardening pass on 2026-05-11. Walk-through order is unchanged: <strong>dataset → model → app → next steps</strong>. Open this file on screen during the meeting; <strong>do not read word-for-word</strong>.<br><br>
  紧接 2026-05-11 v1.0.0 强化提交之后的<strong>进度汇报</strong>会议。顺序一律不变:<strong>dataset → model → app → 下一步</strong>。开会时屏幕上打开本文档,<strong>不要照念</strong>,当兜底用即可。
</div>

<!-- ===== Section 0: what you need to do ===== -->
<h2>0 · What you need to do — three time windows
  <span class="zh">你要做的事 —— 三个时间窗口</span>
</h2>

<h3>0.1 · Before the meeting (T-15 min) / 会前 15 分钟</h3>

<table class="check">
  <tr><th style="width:6%"></th><th>English</th><th>中文</th></tr>
  <tr><td></td><td>Charge laptop ≥ 80 %; charger in bag.</td><td>笔记本充满 ≥ 80%,充电器带上。</td></tr>
  <tr><td></td><td><code>cd ~/Projects/microclimate-x &amp;&amp; git pull &amp;&amp; git status</code> — must print "working tree clean".</td><td>拉最新代码,确认 working tree clean。</td></tr>
  <tr><td></td><td><code>make run</code> in <strong>terminal A</strong> (leave it running).</td><td>终端 A 起后端,<strong>不要关</strong></td></tr>
  <tr><td></td><td><code>curl -s http://localhost:8000/api/health | python3 -m json.tool</code> in <strong>terminal B</strong> — verify <code>"ml_loaded": true</code>.</td><td>终端 B 验证健康检查,<code>ml_loaded</code> 必须为 <code>true</code></td></tr>
  <tr><td></td><td>Open the 10 browser tabs in the order from <code>MEETING_CHEAT_SHEET.md</code> §0 — <strong>app tab is last</strong>.</td><td>按 cheat-sheet §0 顺序开 10 个标签页,<strong>app 标签放最后</strong></td></tr>
  <tr><td></td><td>This file (<code>progress_update_brief.html</code>) open on a separate screen / phone.</td><td>把本文档单独开在副屏或手机上。</td></tr>
  <tr><td></td><td>Phone on silent. Deep breath.</td><td>手机静音,深呼吸。</td></tr>
</table>

<h3>0.2 · During the meeting (≈ 8 minutes) / 会中 ≈ 8 分钟</h3>

<table class="timeline">
  <tr><th>Block</th><th>EN heading</th><th>中文标题</th><th>Time</th></tr>
  <tr><td class="block">1</td><td>Opening 30 s</td><td>开场 30 秒</td><td class="time">0:00 → 0:30</td></tr>
  <tr><td class="block">2</td><td>What changed since last meeting</td><td>自上次会以来的进展</td><td class="time">0:30 → 2:00</td></tr>
  <tr><td class="block">3</td><td>Live demo — dataset → model → app</td><td>现场演示(顺序不变)</td><td class="time">2:00 → 5:00</td></tr>
  <tr><td class="block">4</td><td>Next steps for Chapter 5</td><td>Chapter 5 下一步</td><td class="time">5:00 → 6:30</td></tr>
  <tr><td class="block">5</td><td>Asks + closing</td><td>请示 + 收尾</td><td class="time">6:30 → 8:00</td></tr>
</table>

<h3>0.3 · After the meeting (T+24 h) / 会后 24 小时内</h3>

<table class="check">
  <tr><th style="width:6%"></th><th>English</th><th>中文</th></tr>
  <tr><td></td><td>Write meeting minutes — capture every supervisor decision in <code>docs/meeting_log_&lt;date&gt;.md</code>.</td><td>写会议纪要,把老师每条决定记到 <code>docs/meeting_log_&lt;日期&gt;.md</code></td></tr>
  <tr><td></td><td>Open one GitHub issue per agreed action item (label: <code>chapter-5</code>).</td><td>每个 action item 在 GitHub 开一个 issue,打 <code>chapter-5</code> 标签。</td></tr>
  <tr><td></td><td>Email a 3-bullet summary back to the supervisor for written confirmation.</td><td>给老师发 3 条要点的总结邮件,留<strong>书面确认</strong></td></tr>
  <tr><td></td><td>Update <code>README.md</code> §9 Roadmap — tick boxes that were signed off.</td><td>更新 <code>README.md</code> 第 9 节 Roadmap,把通过的项打勾。</td></tr>
  <tr><td></td><td>Tag a new release if scope was confirmed (<code>git tag v1.1.0-rc.1</code>).</td><td>如果范围确认了,打个新 tag (<code>v1.1.0-rc.1</code>)。</td></tr>
</table>

<!-- ===== Section 1: Opening ===== -->
<h2 class="pb">1 · Opening (30 seconds)
  <span class="zh">开场 30 秒</span>
</h2>

<table class="bilingual">
  <tr>
    <td class="en">"Sir, thank you for your time. Following up on our last session, I've completed a production-grade hardening pass — version 1.0.0 — and the full pipeline is now reproducible end-to-end. May I walk you through what's new in the same order as before — <strong>dataset, then model, then app</strong> — and finish with my proposed plan for Chapter 5?"</td>
    <td class="zh">"老师感谢您抽时间。接着上次的内容,我做完了 <strong>v1.0.0 工程化强化</strong>,整条流水线现在可以<strong>端到端复现</strong>。我按上次的顺序——<strong>dataset、model、app</strong>——给您过一遍新的进展,最后讲我对 Chapter 5 的下一步计划,可以吗?"</td>
  </tr>
</table>

<div class="callout ok">
  <strong>Why this opening · 为什么这样开场</strong>: (a) restates the supervisor's preferred process order without him asking, (b) signals you've made forward progress (not just polish), (c) ends with an explicit ask for direction on Chapter 5 — which is what <em>he</em> wants to talk about.<br>
  (a) 不用他提就主动按他的流程顺序;(b) 强调是<strong>前进了</strong>而不是只在抛光;(c) 用对 Chapter 5 的请示收尾,<strong>这正是他想聊的话题</strong></div>

<!-- ===== Section 2: progress recap ===== -->
<h2>2 · What changed since the last meeting
  <span class="zh">自上次会议以来的进展</span>
</h2>

<p style="color: var(--muted); font-size: 9.5pt;">
  ≈ 90 seconds. Stay on the GitHub repo tab — point to the commit history, the green CI badge, the v1.0.0 release.<br>
  ≈ 90 秒。停在 GitHub repo 标签页,指给老师看 commit 历史、CI 绿勾、v1.0.0 release。
</p>

<table class="bilingual">
  <tr><th style="width:18%">Area / 模块</th><th>English</th><th>中文</th></tr>
  <tr>
    <td><strong>Backend hardening</strong><br><span style="color:var(--muted);font-size:9pt">后端强化</span></td>
    <td>"I added a request-ID middleware, a typed <code>ErrorResponse</code> contract so no bare HTML 500s leak, structured logging, and an enriched <code>/api/health</code> exposing uptime, cache stats, and the loaded ML feature schema."</td>
    <td>"后端我加了 <strong>request-ID 中间件</strong><strong>类型化错误协议</strong> <code>ErrorResponse</code>(不再泄漏裸 HTML 500)、结构化日志、以及<strong>升级版 <code>/api/health</code></strong>(暴露 uptime、缓存统计、ML 特征 schema)。"</td>
  </tr>
  <tr>
    <td><strong>ML pipeline</strong><br><span style="color:var(--muted);font-size:9pt">ML 流水线</span></td>
    <td>"I shipped <code>scripts/4_evaluate_model.py</code> which produces six publication-quality figures plus a machine-readable <code>evaluation_summary.json</code>. I also wrote a HuggingFace-style <code>MODEL_CARD.md</code> covering intended use, training data, metrics, limitations, and ethical considerations."</td>
    <td>"ML 流水线加了<strong>评估脚本</strong> <code>scripts/4_evaluate_model.py</code>,自动出 6 张论文级别图 + 一份 <code>evaluation_summary.json</code>。还写了 HuggingFace 风格的 <strong>MODEL_CARD.md</strong>,覆盖用途、训练数据、指标、局限、伦理考量。"</td>
  </tr>
  <tr>
    <td><strong>Tests + CI</strong><br><span style="color:var(--muted);font-size:9pt">测试 + CI</span></td>
    <td>"Total tests went from 19 to <strong>70</strong>, backend coverage is <strong>97 %</strong>. CI runs on Python 3.9 / 3.11 / 3.12 plus a Docker image-build smoke test."</td>
    <td>"测试数从 19 涨到 <strong>70</strong><strong>后端覆盖率 97%</strong>。CI 跑 Python 3.9/3.11/3.12 矩阵,外加 Docker 镜像构建烟测。"</td>
  </tr>
  <tr>
    <td><strong>Dev-ex</strong><br><span style="color:var(--muted);font-size:9pt">开发体验</span></td>
    <td>"Multi-stage Dockerfile, docker-compose, Makefile single-word recipes, pre-commit hooks. The whole project is now <code>docker compose up --build</code> away from a clean machine."</td>
    <td>"多阶段 Dockerfile + compose + Makefile 单词命令 + pre-commit hooks。<strong>新机器一句 <code>docker compose up --build</code> 就能跑起来</strong>。"</td>
  </tr>
  <tr>
    <td><strong>Documentation</strong><br><span style="color:var(--muted);font-size:9pt">文档</span></td>
    <td>"Three new docs — <code>architecture.md</code>, <code>thresholds.md</code> with citations for every Veto threshold, and <code>pipeline_order.md</code> which explicitly enforces the dataset → model → app order you asked for."</td>
    <td>"三份新文档——<code>architecture.md</code><code>thresholds.md</code>(每个 Veto 阈值都附学术引用)、以及 <code>pipeline_order.md</code><strong>显式按您要求的 dataset→model→app 顺序写死</strong>)。"</td>
  </tr>
</table>

<div class="callout tip">
  <strong>Artefact to show · 展示物</strong>: GitHub commit history page; the green CI badge on the README; <code>CHANGELOG.md</code> v1.0.0 entry.<br>
  GitHub commit 历史页;README 上的 CI 绿勾;<code>CHANGELOG.md</code> 中 v1.0.0 那一段。
</div>

<!-- ===== Section 3: live demo ===== -->
<h2 class="pb">3 · Live demo — dataset → model → app
  <span class="zh">现场演示(顺序不变)</span>
</h2>

<p style="color: var(--muted); font-size: 9.5pt;">
  ≈ 3 minutes. Same order as the 5/11 dry-run script — no surprises for the supervisor.<br>
  ≈ 3 分钟。跟 5/11 的脚本完全一样的顺序,<strong>老师不会被打乱节奏</strong></p>

<div class="step">
  <div class="num">1</div>
  <div class="body">
    <h3>Dataset (Tab <code>docs/dataset.md</code>) — 30 s</h3>
    <table class="bilingual">
      <tr>
        <td class="en">"Same dataset as last time — ERA5 reanalysis, 5 Malaysian mountain sites, 175 315 hourly rows. The Y column <code>is_rain_event</code> is derived in one line and documented in §5. <strong>No change here</strong>, just confirming the foundation is unchanged."</td>
        <td class="zh">"数据集跟上次一样——ERA5 再分析、马来西亚 5 个山地点位、17.5 万行小时数据。Y 列 <code>is_rain_event</code> 一行代码构造,文档在 §5。<strong>这里没有变</strong>,只是确认地基没动。"</td>
      </tr>
    </table>
  </div>
</div>

<div class="step">
  <div class="num">2</div>
  <div class="body">
    <h3>Model (Tabs <code>01_roc</code><code>03_calibration</code><code>04_threshold</code><code>05_feature_importance</code>) — 90 s</h3>
    <table class="bilingual">
      <tr>
        <td class="en">"Same model as last time — Random Forest, time-based split, τ = 0.20. Test ROC AUC <strong>0.871</strong>, PR AP <strong>0.750</strong>, Brier <strong>0.138</strong>, recall <strong>93.4 %</strong>. <strong>What's new is the 6 figures plus the model card</strong> — every number you see here is reproducible from <code>make evaluate</code>."</td>
        <td class="zh">"模型跟上次一样——RF、时间序列切分、τ = 0.20。测试 AUC <strong>0.871</strong>、PR AP <strong>0.750</strong>、Brier <strong>0.138</strong>、召回率 <strong>93.4%</strong><strong>新东西</strong>是 6 张图 + model card——上面任何一个数字都可以用 <code>make evaluate</code> 复现。"</td>
      </tr>
    </table>
  </div>
</div>

<div class="step">
  <div class="num">3</div>
  <div class="body">
    <h3>App (Tab <code>http://localhost:8000/app/</code>) — 60-90 s</h3>
    <table class="bilingual">
      <tr>
        <td class="en">"Step 3, the app — opened <strong>last</strong> as agreed. Two demo scenarios. First, <strong>Genting Highlands</strong> — a slope at 1865 m inside the training distribution. The model gives a moderate rain probability; the rule engine picks up orographic lift; the four mini-gauges decompose the risk by hazard type."</td>
        <td class="zh">"第三步 app——按约定<strong>最后才开</strong>。两个 demo 场景。第一个<strong>云顶高原</strong>——1865 m 的山坡,<strong>在训练分布之内</strong>。模型给中等降雨概率,规则引擎检测到地形抬升,四个 mini-gauge 把风险按灾害类型拆解。"</td>
      </tr>
      <tr>
        <td class="en">"Second, <strong>Mt Everest</strong> — completely out of distribution. The model alone would say 'safe'. The Veto cascade fires three independent overrides — hypoxia, frostbite, gale — and the composite is forced to Danger. There's a unit test for exactly this: <code>test_mt_everest_veto_hypoxia</code>."</td>
        <td class="zh">"第二个<strong>珠峰</strong>——<strong>完全分布外</strong>。光看模型会说"安全",但 Veto 级联触发<strong>三个独立否决</strong>——缺氧、冻伤、大风——综合分被强制设为 Danger。<strong>专门有单元测试覆盖这个场景</strong><code>test_mt_everest_veto_hypoxia</code>。"</td>
      </tr>
    </table>
  </div>
</div>

<!-- ===== Section 4: Chapter 5 plan ===== -->
<h2 class="pb">4 · Next steps for Chapter 5
  <span class="zh">Chapter 5 下一步</span>
</h2>

<div class="callout warn">
  ≈ 90 seconds. <strong>This is the section the supervisor will react to most.</strong> Frame each item as a concrete deliverable + estimated time + dependency.<br>
  ≈ 90 秒。<strong>老师反应最强烈的就是这一节</strong>。每一项都以"<strong>交付物 + 估时 + 依赖</strong>"形式呈现。
</div>

<h3>4.1 · Proposed Chapter 5 work plan / Chapter 5 工作计划</h3>

<table class="plan">
  <tr><th>#</th><th>Deliverable / 交付物</th><th>EN one-liner</th><th>中文一句话</th><th class="estimate">Estimate</th></tr>
  <tr>
    <td><span class="pill plan">5.1</span></td>
    <td><strong>Comparative ablation</strong><br><span style="color:var(--muted);font-size:9pt">对比实验</span></td>
    <td>"Train LogReg + XGBoost on the same features and report ROC / PR / F2 side-by-side with RF — answers 'why RF?' empirically."</td>
    <td>"在同一特征集上训 LogReg + XGBoost,对比 ROC / PR / F2,<strong>用数据回答"为什么选 RF"</strong>。"</td>
    <td class="estimate">1 week</td>
  </tr>
  <tr>
    <td><span class="pill plan">5.2</span></td>
    <td><strong>Hindcast validation</strong><br><span style="color:var(--muted);font-size:9pt">历史事件回放</span></td>
    <td>"Replay 2020-2024 NaDMA-documented Malaysian flood / landslide events and check whether the system would have raised Warning / Danger at the right time. Reports hit-rate, lead-time, false-alarm rate."</td>
    <td>"把 2020-2024 NaDMA 公开的马来西亚洪水/滑坡事件<strong>逐一回放</strong>,看系统能否在事发前给出 Warning/Danger。报告命中率、提前量、误报率。"</td>
    <td class="estimate">2 weeks</td>
  </tr>
  <tr>
    <td><span class="pill plan">5.3</span></td>
    <td><strong>Threshold sensitivity</strong><br><span style="color:var(--muted);font-size:9pt">阈值灵敏度</span></td>
    <td>"Sweep τ ∈ {0.10, 0.15, 0.20, 0.25, 0.30}, plot precision-recall trade-off, and justify the operating point with a cost-of-error analysis."</td>
    <td>"扫 τ ∈ {0.10, 0.15, 0.20, 0.25, 0.30},画精度-召回权衡曲线,用<strong>误差代价分析</strong>为最终选点辩护。"</td>
    <td class="estimate">3 days</td>
  </tr>
  <tr>
    <td><span class="pill plan">5.4</span></td>
    <td><strong>Component ablation</strong><br><span style="color:var(--muted);font-size:9pt">组件消融</span></td>
    <td>"Compare three system variants — RF only / Rule only / Hybrid — on the held-out test set and on the OOD Mt Everest case. Quantifies the rule-engine contribution."</td>
    <td>"对比三个系统变体——<strong>纯 RF / 纯规则 / 混合</strong>——在测试集和 OOD 珠峰场景上的表现。<strong>量化规则引擎的贡献</strong>。"</td>
    <td class="estimate">4 days</td>
  </tr>
  <tr>
    <td><span class="pill risk">5.5</span></td>
    <td><strong>Small user study</strong> <em>(optional)</em><br><span style="color:var(--muted);font-size:9pt">用户研究(可选)</span></td>
    <td>"Recruit 5-8 mountain hikers, run a 4-week panel, log system advice vs. their field judgment. Reports inter-rater agreement (Cohen's κ)."</td>
    <td>"招募 5-8 名登山者,4 周面板研究,记录系统建议 vs 他们现场判断,报告 Cohen's κ 一致性。"</td>
    <td class="estimate">4 weeks</td>
  </tr>
  <tr>
    <td><span class="pill done">5.6</span></td>
    <td><strong>Thesis Chapter 5 draft</strong><br><span style="color:var(--muted);font-size:9pt">章节初稿</span></td>
    <td>"Pull §5.1-5.5 into a single 12-15 page evaluation chapter with all figures, tables, and discussion."</td>
    <td>"把 §5.1-5.5 整合成 12-15 页的评估章节,含全部图表和讨论。"</td>
    <td class="estimate">1 week</td>
  </tr>
</table>

<h3>4.2 · Decision tree to ask the supervisor / 请示决策树</h3>

<div class="decision">
  <div class="decision-title">Q1 · Priorities</div>
  <table class="bilingual">
    <tr>
      <td class="en">"Sir, of the five evaluation tracks above, <strong>which two should I prioritise for the next four weeks</strong> before we converge on the Chapter 5 outline?"</td>
      <td class="zh">"老师,上面 5 条评估方向,<strong>未来四周</strong>您建议我重点做哪两条,然后再收敛到 Chapter 5 大纲?"</td>
    </tr>
  </table>
</div>

<div class="decision">
  <div class="decision-title">Q2 · User study yes/no</div>
  <table class="bilingual">
    <tr>
      <td class="en">"Do you want me to include the user study (5.5)? It is the longest item and depends on participant recruitment — I want your call before committing."</td>
      <td class="zh">"<strong>用户研究 (5.5) 您要不要做</strong>?这一条最长、依赖招募——想请您拍板再投入。"</td>
    </tr>
  </table>
</div>

<div class="decision">
  <div class="decision-title">Q3 · Framing of the comparative study</div>
  <table class="bilingual">
    <tr>
      <td class="en">"For the comparative ablation, do you want it framed as <strong>'why RF wins'</strong> (defending current choice) or <strong>'what if XGBoost wins'</strong> (open exploration)? The framing affects how I report inconclusive results."</td>
      <td class="zh">"<strong>对比实验</strong>您希望框成"为什么 RF 胜出"(<strong>捍卫现有选择</strong>)还是"如果 XGBoost 更好怎么办"(<strong>开放探索</strong>)?两种 framing 对<strong>模棱两可结果</strong>的报告方式不同。"</td>
    </tr>
  </table>
</div>

<div class="decision">
  <div class="decision-title">Q4 · Mt Everest weight in the thesis</div>
  <table class="bilingual">
    <tr>
      <td class="en">"Should I treat the Mt Everest OOD test as a <strong>thesis-level contribution</strong> (a stand-alone subsection on safety) or just an <strong>appendix item</strong>?"</td>
      <td class="zh">"<strong>珠峰 OOD 测试</strong>算论文级别的贡献(单独一节讲安全性),还是放附录就够?"</td>
    </tr>
  </table>
</div>

<!-- ===== Section 5: closing ===== -->
<h2 class="pb">5 · Asks + closing (60 seconds)
  <span class="zh">请示 + 收尾 60 秒</span>
</h2>

<table class="bilingual">
  <tr>
    <td class="en">"Sir, to summarise: since the last meeting I've shipped v1.0.0 — production-grade hardening, 70 tests at 97 % coverage, six evaluation figures, a published model card, full Docker reproducibility. The pipeline order is unchanged from what you asked: <strong>dataset, model, app</strong>. For Chapter 5 I have <strong>five evaluation tracks scoped</strong>; I'd like your guidance on which two to prioritise for the next four weeks."</td>
    <td class="zh">"老师,总结:自上次会议以来交付了 <strong>v1.0.0</strong>——工程化强化、70 个测试 97% 覆盖率、6 张评估图、model card、Docker 全复现。流水线顺序按您要求<strong>没动</strong>:dataset、model、app。Chapter 5 我列了 <strong>5 条评估方向</strong><strong>接下来四周您建议我先做哪两条</strong>?"</td>
  </tr>
  <tr>
    <td class="en">"I'll send you a 3-bullet email summary by tomorrow morning so we have <strong>written agreement</strong> on the priorities. Thank you for your time."</td>
    <td class="zh">"明早之前给您发 3 条要点的邮件总结,<strong>留个书面确认</strong>。谢谢老师。"</td>
  </tr>
</table>

<!-- ===== Section 6: defensive Q&A ===== -->
<h2>6 · Q&amp;A defensive lines (this update only)
  <span class="zh">本次进度汇报的兜底话术</span>
</h2>

<div class="callout tip">
  Anticipated follow-up questions <strong>specific to this progress update</strong>. The classic Q1-Q7 from the 5/11 brief are still live — just don't repeat them here.<br>
  <strong>针对本次进度汇报</strong>可能出现的追问。5/11 那份的经典 Q1-Q7 仍然有效,不重复罗列。
</div>

<h3>Q-N1 — "Why are you spending time on tests and Docker instead of the thesis?"</h3>
<h3 style="margin-top:-2mm">Q-N1 ——为什么你在写测试和 Docker 上花时间,不写论文?</h3>

<table class="bilingual">
  <tr>
    <td class="en">"Sir, the v1.0.0 hardening was a <strong>one-time investment</strong> to make every Chapter 5 number reproducible by the examiner with a single command. Without it, every evaluation result would be a black box — the examiner could not verify the AUC of 0.871 herself. With <code>make evaluate</code> reproducing all six figures byte-for-byte, the thesis claims become <strong>falsifiable</strong>. From this point on, all my time goes to evaluation and writing."</td>
    <td class="zh">"老师,v1.0.0 的强化是<strong>一次性投资</strong>——为了让评审老师<strong>用一行命令就能复现 Chapter 5 的每一个数字</strong>。没有它,AUC = 0.871 就是黑盒,<strong>评审无法独立验证</strong>。现在 <code>make evaluate</code> 能把 6 张图按字节复现,论文的每个 claim 都<strong>可证伪</strong>。从今天起所有时间都给评估和写作。"</td>
  </tr>
</table>

<h3>Q-N2 — "Why hasn't the model improved since last time?"</h3>
<h3 style="margin-top:-2mm">Q-N2 ——模型为什么自上次以后没提升?</h3>

<table class="bilingual">
  <tr>
    <td class="en">"Two reasons. First, the supervisor's instruction was to <em>consolidate</em> dataset and model before adding more capacity — which is what I did. Second, the bottleneck right now is <strong>not the model</strong> but the <strong>rule engine's coverage of OOD scenarios</strong>, which is a Chapter 5 contribution rather than a hyperparameter tweak. I'd rather report a defensible 0.871 with a calibrated rule engine than chase 0.88 with an unprincipled stack."</td>
    <td class="zh">"两个理由:(1) 您上次的指示是<strong>先把 dataset 和 model 巩固好</strong>再加复杂度——我严格照做了。(2) <strong>当前瓶颈不是模型本身</strong>,而是<strong>规则引擎对 OOD 场景的覆盖</strong>——这是 Chapter 5 的研究贡献,不是调超参。我宁愿报一个<strong>可辩护的 0.871</strong> 加一个校准好的规则引擎,<strong>也不要不讲原理地堆栈到 0.88</strong>。"</td>
  </tr>
</table>

<h3>Q-N3 — "Show me one concrete weakness you have not yet fixed."</h3>
<h3 style="margin-top:-2mm">Q-N3 ——给我说一个你目前还没修的具体弱点。</h3>

<table class="bilingual">
  <tr>
    <td class="en">"Honestly, Sir, the biggest one is <code>cape_jkg</code> — the ERA5 archive returns predominantly zero CAPE for these Malaysian coordinates, which is a <strong>known coverage gap</strong>. The Random Forest learns nothing from it (0 % importance). The rule engine still uses live Open-Meteo CAPE at inference time, so the production output is fine, but the <em>training</em> signal for thunderstorm risk is weaker than I'd like. I plan to address this in §5.4 ablation by quantifying how much it matters."</td>
    <td class="zh">"老实说,老师,最大的弱点是 <code>cape_jkg</code>——ERA5 在这些马来西亚坐标上的 CAPE 几乎全为零(<strong>已知覆盖缺口</strong>),<strong>RF 完全没学到东西</strong>(特征重要性 0%)。规则引擎在推理时用的是 Open-Meteo 实时 CAPE,所以生产输出没问题,但<strong>雷暴风险的训练信号</strong>比我希望的弱。计划在 §5.4 消融实验里<strong>量化它的影响</strong>。"</td>
  </tr>
</table>

<h3>Q-N4 — "When can I see the first draft of Chapter 5?"</h3>
<h3 style="margin-top:-2mm">Q-N4 ——Chapter 5 初稿什么时候能给我看?</h3>

<table class="bilingual">
  <tr>
    <td class="en">"If you sign off on tracks <strong>5.1 + 5.2 + 5.4</strong> today, the data collection finishes in 3 weeks, writing takes 1 week, so you'd have a draft in <strong>4 weeks from today</strong>. If you also want 5.5 (user study), add 4 weeks. <strong>I'll lock the date the moment you confirm the scope.</strong>"</td>
    <td class="zh">"如果今天您拍板 <strong>5.1 + 5.2 + 5.4</strong> 三条,<strong>3 周收数据 + 1 周写作 = 4 周后给您初稿</strong>。如果再加 <strong>5.5(用户研究)</strong>,再加 4 周。<strong>您一确认范围,我立刻锁定交稿日</strong>。"</td>
  </tr>
</table>

<!-- ===== Section 7: pre-flight checklist ===== -->
<h2 class="pb">7 · Pre-flight checklist (T-60 sec)
  <span class="zh">起飞前 60 秒自检</span>
</h2>

<div class="check">
<pre><code>☐ Laptop ≥ 80 % battery, charger in bag
☐ Terminal A: `make run` is running, do not close
☐ Terminal B: `curl /api/health` returned ml_loaded: true within last 5 min
☐ 10 browser tabs open in cheat-sheet §0 order — app tab is LAST
☐ This file open on a separate screen / phone, NOT to be read aloud
☐ docs/MEETING_CHEAT_SHEET.md open as a fall-back
☐ models/MODEL_CARD.md open in case any number is challenged
☐ figures/evaluation_summary.json downloadable on demand
☐ Phone on silent
☐ One deep breath. You shipped v1.0.0. You're prepared.</code></pre>
</div>

<div class="check">
<pre><code>☐ 笔记本电池 ≥ 80%,充电器已带
☐ 终端 A:`make run` 跑着,不要关
☐ 终端 B:5 分钟内 `curl /api/health` 返回 ml_loaded: true
☐ 10 个浏览器标签页按 cheat-sheet §0 顺序开好——app 标签放最后
☐ 本文档开在副屏 / 手机,不要照念
☐ docs/MEETING_CHEAT_SHEET.md 开着兜底
☐ models/MODEL_CARD.md 开着,老师质疑任何数字立刻打开
☐ figures/evaluation_summary.json 随时可发
☐ 手机静音
☐ 深呼吸。v1.0.0 已经交付。你准备好了。</code></pre>
</div>

<!-- ===== Section 8: cross references ===== -->
<h2>8 · Cross-references
  <span class="zh">相关文档索引</span>
</h2>

<table>
  <tr><th>Topic / 主题</th><th>File / 文件</th></tr>
  <tr><td>Original 5/11 reply to 4/15 feedback</td><td><a href="supervisor_meeting_brief.md"><code>supervisor_meeting_brief.md</code></a></td></tr>
  <tr><td>One-page cheat sheet (tab order, demo script)</td><td><a href="MEETING_CHEAT_SHEET.html"><code>MEETING_CHEAT_SHEET.html</code></a></td></tr>
  <tr><td>Pipeline order ASCII chart</td><td><a href="pipeline_order.md"><code>pipeline_order.md</code></a></td></tr>
  <tr><td>Dataset spec + Y derivation</td><td><a href="dataset.md"><code>dataset.md</code></a></td></tr>
  <tr><td>Architecture deep-dive</td><td><a href="architecture.md"><code>architecture.md</code></a></td></tr>
  <tr><td>Threshold citations</td><td><a href="thresholds.md"><code>thresholds.md</code></a></td></tr>
  <tr><td>Model card</td><td><a href="../models/MODEL_CARD.md"><code>../models/MODEL_CARD.md</code></a></td></tr>
  <tr><td>Evaluation summary JSON</td><td><a href="../figures/evaluation_summary.json"><code>../figures/evaluation_summary.json</code></a></td></tr>
  <tr><td>What changed in v1.0.0</td><td><a href="../CHANGELOG.md"><code>../CHANGELOG.md</code></a></td></tr>
</table>

<footer>
  Generated 2026-05-13 for the MicroClimate-X progress-update meeting at UKM.<br>
  此页为 2026-05-13 UKM 毕业设计 MicroClimate-X 进度汇报准备文档。<br>
  <span style="color: var(--brand);">L.ZH @ UKM · KyoukoLi/microclimate-x</span>
</footer>

</main>

</body>
</html>