planning-session-synth · git:20260918.2429d96 · 2026-09-18 · sha256 67f5e65e8a891119
planning-session-synth git:20260918.2429d96A
Immutable. This exact content never changes and is served at /api/v1/blob/67f5e65e8a891119.
--- name: planning-session-synth sheetId: "0.06" description: >- Same-day digestion of a Zynkr planning offsite (H1 / H2 / year-end): turn the session transcript + whiteboard photos into the Main Tracker's working tabs — verbatim 「② 白板原文」 (pen colour + 判讀信心 高/中/低), the MECE re-cut 「③ 去重與歸類決策」 + 「④ MECE 檢查」 with every merge/split/move ruling written down, the 「<cycle> 回顧總結」 retro table with 5 重點結論, the README tab, a normalized item list handed to planning-tracker-builder, and the recap mail as a Gmail DRAFT (never sent). Trigger on /planning-session-synth or when Peter says "整理 offsite 白板", "白板轉 tracker", "整理 planning 逐字稿", "做回顧總結", "H2/年度 planning recap", "digest the planning session", "whiteboard to tracker", or hands over an offsite transcript and/or board photos. Distinct from project-note-specialist / consult-session-notes (tidy ONE meeting into a Summary/Progress/Blockers/Next shape — no whiteboard, no MECE tabs), from curate-livestream-transcripts (weekly batch summaries of livestream Docs), from planning-tracker-builder (takes THIS skill's item list and adds owners / priority / the SOR tab), and from planning-prework-pack (before the room). category: strategy project: planning-session-synth platform: claude status: Done author: Peter Tu input: "Cycle (H1/H2/YE) + transcript (Doc ID, pasted text or Fireflies recap) + whiteboard photo(s) (Drive image IDs or local files); optional speaker map, recap recipients, tracker ID" process: "Resolve cycle + sources → fetch transcript + photos → Pass A verbatim ② 白板原文 → Pass B MECE re-cut ③ + ④ + normalized list → transcript pass: speaker turns → 回顧總結 + 5 重點結論 → README + 請與會者確認 → tabs into the tracker (row plan first) → recap-mail Gmail DRAFT" output: "Tabs README · <cycle> 回顧總結 · ② 白板原文 · ③ 去重與歸類決策 · ④ MECE 檢查 in the Main Tracker, a normalized item list for planning-tracker-builder, and a recap-mail Gmail DRAFT (never sent)" synergy: - "planning-tracker-builder" - "planning-prework-pack" - "planning-tracker-sync" - "project-note-specialist" - "consult-session-notes" - "curate-livestream-transcripts" house-style: bound --- # Planning Session Synth ```bash npx skills add https://github.com/peter-tu-zynkr/zynkr-skill-builder --skill planning-session-synth ``` The offsite ends with a whiteboard nobody can search and a transcript nobody will re-read; this skill turns both into the Main Tracker the same evening — verbatim board rows first, then a MECE re-cut whose every merge/split/move is a written, disputable ruling, then the retro table and the recap mail. It is for the founder (or whoever facilitated) on the day of an H1 / H2 / year-end planning session, before the memory of what a scrawl meant has faded. Unlike "summarise this meeting", it transcribes before normalising, marks every uncertain reading, applies last cycle's rulings as precedent, and flags the LOBs the room forgot instead of inventing items for them. --- ## How this differs from its neighbours - **planning-tracker-builder** — downstream: takes this skill's normalized item list, adds the room's owner / 重要×緊急 decisions, builds the SOR tab (`<cycle> 專案項目`) with lint. This skill stops at the item list unless told to write the SOR tab; when this run created the cycle's tracker, the builder fills its empty SOR tab in place (`fill` mode) — one cycle, one file. - **planning-prework-pack** — upstream, before the room (workbook · deck · pre-work); its 「Laundry List」 seeds are a cross-check for Pass B, never a substitute for the board. - **planning-tracker-sync** — the weekly agenda block off the finished tracker. - **project-note-specialist / consult-session-notes / curate-livestream-transcripts** — pattern sources only (turn-segmentation, evidence-first rows, Doc → zh-TW summary). Their output shapes are wrong here — do not delegate to them. ## Fixed facts (read the references first) - `./references/planning-knowledge-pack.md` — taxonomy (§2), priority rule (§3), runbook + recap-mail shape (§5), tracker layout (§6), the 17 MECE rulings (§7), versioning (§8), never-do list (§9). Byte-identical across the family; do not edit. - `./references/planning-sources.md` — every live ID: hub folder, Main Tracker + tab gids, transcript Doc, `Image/` photo IDs, per-LOB plan Docs (§A); Fireflies / calendar / 1:1 evidence (§B); team conventions (§C). Never hard-code an ID in a reply — quote it from this file. - `./references/tracker-tab-schemas.md` — the write contract for Steps 2–8: header rows, layouts, 領域 vocabulary, one worked example row per tab, the handoff shape, README keys, recap-mail skeleton. - Google account for every `google-workspace` call: `peter_tu@zynkr.ai` (user may override). Sheets: `read_sheet_values` / `modify_sheet_values` / `create_sheet`; Docs: `get_doc_as_markdown`; photos: `get_drive_file_download_url` (stdio mode returns a local path under `~/.workspace-mcp/attachments/` with no extension — copy to a `.jpg` scratch path first, Step 1; HTTP mode a 1-hour URL to fetch) → the `Read` tool views the image; HEIC → `sips -s format jpeg <in>.HEIC --out <out>.jpg` first (macOS). - Status strings and the date placeholder are the pack §3 literals: `未開始 · 進行中 · 完成 · 放棄`, `YYYY-MM-DD`. ## Hard rules 1. **Verbatim before normalised.** Pass A (`② 白板原文`) is finished before any merging, renaming or classifying begins. Crossed-out words, arrows and layout labels all get a row — they are excluded later by a written ruling, never skipped. 2. **Every uncertain reading is surfaced.** Each ② row carries 判讀信心 高/中/低; every 中/低 row lands in the README `請與會者確認` list with candidate readings. Never silently pick one (pack §7 tail, §9). 3. **Rulings are precedent; new rulings are written down.** Apply pack §7 #1–#17 where the case matches; every merge / split / move / keep-separate / exclude — matched or fresh — becomes a numbered row in `③`. No unrecorded re-cut. 4. **Coverage check is mandatory.** Count items per L1 (all eight) into `④`; flag 0 / thin LOBs as 覆蓋缺口 with a quote from that LOB's plan Doc (pack §2). Flag, never fill. 5. **No owners, dates, priorities or numbers you did not hear.** Retro rows and the item list carry only what the transcript / board say; owners come later from the tracker's 負責人 column or the user (pack §9). The recap's owner table is filled only from a tracker that already has owners. 6. **Drafts, never sends.** The recap mail is a Gmail DRAFT to the recipients the user names; if the user says "send", still draft and stop. 7. **Row plan before any Sheet or Drive write** — including creating a new tracker (Step 5): the `create_spreadsheet` / `update_drive_file` calls are lines of the printed plan and run only after the user confirms it. Never touch the SOR tab (`<cycle> 專案項目`) unless told, and never overwrite a tab that has content — version by new tab. "Has content" = at least one data row below the header; a missing or header-only tab is empty and is written in place. Pack §8 names Sheet versions `<name> — YYYY-MM 現行版`; this skill uses the finer `<tab> — YYYY-MM-DD` because two digest runs can land in one month — say so in the README when you do. README itself is the exception: never suffixed, never overwritten — a dated section goes on top of the previous rows (Step 5–6). 8. **Speakers stay 未標示** unless the user supplies a speaker map; inferred turns are `講者A/B/…(推測)`, never a real name. This is a rule about *inference and examples*, not about board text: when the as-is board's column headers are person names written on the board, the ② 白板欄位 label is that header text as written — board text is data, not an example payload. Only the schemas' worked examples and this file stay name-free. 9. **Never renumber L1.** The eight L1 codes and their order are pack §2 fixed (pack §9); a cycle may rename L2 rows (say so in the README) but `1.0 … 8.0` never move. 10. **One cycle, one file.** The sources §A tracker is a write target only when its cycle label matches the requested cycle (Step 0); any other cycle gets its own tracker (Step 5, after confirmation, or the builder's `fresh`) — never mix cycles in one SOR file. --- ## Workflow ### Step 0 — Resolve cycle + sources Read `./references/planning-sources.md`. Take from the user: `cycle` (H1 / H2 / YE — ask if absent; never assume), the session date, and any ID overrides (transcript Doc, photo IDs or local paths, an existing tracker, recipients, a speaker map). Defaults come from sources §A (hub folder, `Image/` folder). **The sources §A Main Tracker is the default target ONLY when its cycle label (title + `<cycle> 專案項目` tab) matches the requested cycle.** For a different cycle (the usual YE case) with no explicit tracker ID, do NOT write into it — resolve `tracker = "new"`: create the new cycle's tracker in Step 5 (after confirmation) or hand to `planning-tracker-builder` `fresh`. Never mix two cycles in one SOR file. Print one line before doing anything else: `Operating on cycle <X> · session <date> · tracker <id or "new"> · photos <n> · transcript <source>`. Also print the tab names you will use: the retro tab `<cycle> 回顧總結` (pack §6 default; the July tracker labels it by the half it looks back on, `H1 回顧總結` — take the user's label) and the SOR tab `<cycle> 專案項目` (schemas §0). ### Step 1 — Fetch the inputs - **Transcript** — Doc ID → `get_doc_as_markdown`; pasted text → as is; Fireflies recap → `search_gmail_messages` `from:fireflies.ai subject:"Fireflies recap" after:<date>` → `get_gmail_message_content`. Note the shape: punctuated or not, speaker-labelled or not. The July Doc in sources §A is punctuated but is raw ASR output — every character space-separated, with heavy homophone errors (好好 = Hahow · 直牙課 = 職涯課 · 巨將 = 巨匠 · 常委 = 長尾 · 玩課率 = 完課率) — expect that. **Normalise first, before any segmenting**: collapse intra-word spaces, build a homophone glossary from context (proper nouns, course names, metrics) and apply it, and keep a 「原句」 next to every line you corrected so a wrong fix stays disputable. Expect a Part-1-only transcript (looking back): then the Step 4 side list `逐字稿裡的決策` is legitimately empty — say so, do not mine Part 1 for decisions. - **Photos** — Drive IDs → `get_drive_file_download_url` → local file (fetch into a temp dir if HTTP mode). In stdio mode the file lands at `~/.workspace-mcp/attachments/<name>_<hash>` — **no extension, spaces in the name** — so copy it to a scratch path ending in `.jpg` (`cp "<that path>" /tmp/board-1.jpg`) before viewing or cropping; convert HEIC → `Read`. Per-column full-resolution crops with PIL are **mandatory**, not optional (`Image.open(f).crop((l, t, r, b))` — offset-exact; `sips -c` only crops from the centre, use it as a last resort): red pen is unreadable at thumbnail size, and the crops are what keep 判讀信心 honest. Record file names + boards / columns / pen colours seen. - If either input is missing, say so and run the half you have; never fabricate the other. ### Step 2 — Pass A: verbatim transcription → `② 白板原文` For each photo, each column left→right, each line top→bottom: one row `# · 白板欄位 · 手寫原文 · 筆色 · 判讀信心 · 備註` per schemas §1. Rules: character-for-character (arrows, layout labels, strike-throughs included), pen colour as seen — when the colour itself is uncertain (dark blue vs black on a photo) write `藍/黑` and set 判讀信心 no higher than 中 — 判讀信心 高/中/低, 備註 with candidate readings for 中/低 and `非工作項` for layout marks. If more than one board, prefix 白板欄位 with the board name (`to-be · Sales`, `as-is · 第 3 欄`); when a column header is a person's name written on the board, the 白板欄位 label is that name as written (hard rule 8 — board text is data). Print the total line count and the count of 中/低 rows. **Do not normalise anything in this pass.** ### Step 3 — Pass B: MECE re-cut → `③` + `④` + the normalized list 1. Classify every work-item row of ② into L1/L2 by *what is produced* (pack §2 rules); layout labels → 排除. Use the pack §2 L2 codes, not the July tab's: the live `④` wrote several L2 numbers that differ from the pack default (講師 3.1 vs 3.2, dogfood 3.4 vs 3.5, Metrics 3.3 vs 3.4 — schemas §3); the pack wins for a new cycle. 2. Walk pack §7 #1–#17 first; where a board item matches a precedent, apply it and cite the number. Then rule on every remaining duplicate / composite / misfiled item with one of 合併 · 拆分 · 移欄 · 不合併 · 排除. **Every** ruling becomes a `③` row (`# · 決策 · 項目 · 白板出處 · 歸到哪裡 · 判準/理由`, schemas §2), fresh ones numbered after the precedents. A ruling that hinges on a 中/低 reading (pack §7 #2 turns on whether the board says 「投標」 or 「槓桿」) is applied **conditionally**: write it with `(待確認 ②#n)` in 判準/理由 and add that ②#n to the confirmation set — never let a guessed character silently decide a merge. 3. Build `④` (schemas §3): 窮盡性 — all eight L1 with 項目數 · 涵蓋程度 · 說明; 互斥性 — each overlap with 重疊處 · 白板寫在哪 · 切法 · 判準. For every L1 at 0 or thin (5.0 / 6.0 / 8.0 are the usual gaps, pack §2) open that LOB's plan Doc (sources §A) and quote what should have been there — the quote is the 說明. Prefer the newest dated addendum inside the Doc over its original body. If the sources §A entry is a Drive *shortcut*, `get_drive_file_permissions` returns the **target's** metadata — take the Doc ID from its `ID:` line and read that; name the resolved ID in the 說明. 4. Emit the normalized item list `主類別 · 子類別 · 項目(正規化)· 出處 · 信心` (schemas §5), grouped 1.0→8.0, no owner / 重要 / 緊急 / dates. Print 原文行數 → 正規化後項目 and the 合併 / 拆分 / 移欄 / 不合併 / 排除 group counts (they feed the README). ### Step 4 — Transcript pass → `<cycle> 回顧總結` 1. **Segment** the normalised text (Step 1 — spaces collapsed, homophones fixed, 原句 kept) into speaker turns on cues (「OK 那換…」「我這邊…」「換你」 「接下來…」「謝謝」, topic resets, first-person switches). Label turns `講者A/B/…(推測)` or apply the user's speaker map; otherwise speakers are 未標示. Cross-check turn order against the as-is board's column order when that photo exists — say whether they agree; do not force it. 2. **Extract retro rows** `# · 領域 · 類型 (做得好/可加強) · 項目 · 逐字稿重點 · 建議下一步` with the pack §6 領域 vocabulary (add a 領域 only if the material demands it, and say so). 逐字稿重點 paraphrases what was said with any number the speaker gave; 建議下一步 is one clause sharpening what the room proposed, or `—` — never a new owner / date / target (hard rule 5). Group by 領域, 做得好 before 可加強. 3. **Count** 做得好 vs 可加強 and per-領域 totals; write the **5 重點結論** on top — the cross-cutting reads (what the period was, the shared problem, the levers, the management gaps, the open decisions), each traceable to rows below. 4. Any explicit 重要/緊急/owner statements from Part 2 (looking forward) go into a side list `逐字稿裡的決策` for planning-tracker-builder — not into the item list. A Part-1-only transcript leaves this list legitimately empty: print `逐字稿裡的決策:0 (逐字稿僅含回顧段)` rather than reading decisions into retro talk. ### Step 5 — Resolve the tracker and write the tabs - **Existing tracker for THIS cycle** (sources §A only when its cycle matches — Step 0; or the user's ID): `get_spreadsheet_info` → list tabs; a header-only or missing tab is written in place; a tab with data rows is never overwritten — `create_sheet(sheet_name= "<tab> — YYYY-MM-DD")` first, then `modify_sheet_values` into that new tab (hard rule 7 — this skill's day-suffixed form of pack §8; the `create_sheet` line is part of the plan). So when the working tabs already hold last cycle's data, this run's four tabs are all day-suffixed: `② 白板原文 — YYYY-MM-DD` · `③ 去重與歸類決策 — YYYY-MM-DD` · `④ MECE 檢查 — YYYY-MM-DD` · `<cycle> 回顧總結 — YYYY-MM-DD`. **README is the one exception — it is never day-suffixed**: it stays a single tab and gets a dated section (`## YYYY-MM-DD digest` title row + this run's key · value rows + one blank spacer) written at the *top*, with the previous cycle's README rows kept intact below (Step 6). - **No tracker for this cycle** (the usual YE case — the session runs before any tracker exists): do **not** create anything yet. Put two lines at the top of the row plan — `create_spreadsheet(title="<year> <cycle> Planning Main Tracker", sheet_names=[README, <cycle> 回顧總結, <cycle> 專案項目, 專案項目小記, ② 白板原文, ③ 去重與歸類決策, ④ MECE 檢查])` → `update_drive_file(add_parents=<hub folder id, sources §A>, remove_parents="root")` — and run them only after the plan is confirmed, printing the new ID. Leave `<cycle> 專案項目` and `專案項目小記` **completely empty — no header row**: an empty SOR tab is what makes `planning-tracker-builder` pick its `fill` mode and write into *this* file; a header row with no L1 blocks would push it into `extend` and stop it, and a builder `fresh` run on top would produce a second tracker beside this one. Alternative, only if the user prefers the builder to own the file: stop before creating, run `/planning-tracker-builder` fresh mode first (it `copy_drive_file`s the sources §A tracker into the hub folder and empties `②/③/④` + the retro tab below their headers), then re-enter this step with the new ID as an **existing tracker**. Say which path you took in the README and Step 9. - **Row plan first** (hard rule 7): the create/move lines above (new tracker only), then per tab the header row + row count + first three rows + target ranges. On confirmation write with `modify_sheet_values` (`value_input_option="RAW"` so `YYYY-MM-DD` and `1.01` stay literal), ≤200 rows per call: `② 白板原文` → `③ 去重與歸類決策` → `④ MECE 檢查` → `<cycle> 回顧總結` (重點結論 rows 1–6, header row 8, rows from 9 — schemas §4). Print each tab's `…/edit#gid=<gid>` URL. ### Step 6 — README tab + 請與會者確認 Write the README key · value rows exactly per schemas §6: what the sheet is, axis choice, why the re-cut, how exclusivity was judged, 原文行數, 正規化後項目 with group counts, 判讀信心 counts, the **`請與會者確認` list** (every 中/低 ② row + candidate readings, hard rule 2), `⚠ 覆蓋缺口` / `⚠ 偏薄` lines with plan-Doc quotes, 回顧總結 counts + speaker note, 分頁導覽. Same row-plan-then-write discipline. On a tracker whose README already has rows (re-run / new cycle in the same file): `read_sheet_values` the existing README first, then write the dated section on top and re-emit the previous rows unchanged below it — the row plan shows the full resulting range; the previous cycle's README rows are never overwritten or dropped, and the README tab is never day-suffixed (Step 5). Include the conditional rulings' `(待確認 ②#n)` items in `請與會者確認`. ### Step 7 — Hand off the normalized item list Default: print the list (schemas §5) in the chat and name the next command (`/planning-tracker-builder <tracker ID>` with this list + the room's owner / 重要×緊急 decisions; say `mode = fill` when this run created the tracker with an empty SOR tab). The chat is not durable and `③`/`④` carry rulings and counts, not every item — so the default persistence is chat handoff **plus** a `.md` in the hub folder (`create_drive_file`, name `<year>-<cycle>-normalized-items-YYYY-MM-DD.md`), written only after the user confirms that plan line. A `⑤ 正規化清單` tab is an OPTIONAL extra — it is not in pack §6's layout — written only when the user asks (header = the schemas §5 columns, row plan first, same never-overwrite rule). Print which was written, and its ID. Only when the user says "write it into `<cycle> 專案項目`": SOR header, L1 header rows, `N.NN` numbering, 重要 / 緊急 / Priority / 負責人 blank, dates `YYYY-MM-DD`, 狀態 `未開始` — row plan, write on confirmation, and say plainly that priority, owners and dates are still unset. ### Step 8 — Recap mail as a Gmail DRAFT Draft in zh-TW to the recipients the user named (ask once if none; an empty `to` is acceptable only when the user explicitly says "just draft"). **If no recipients were named and the run is non-interactive** (no one to ask — a scheduled or one-shot run): print the full draft text in the chat and STOP — do not create a `to=""` draft; say `recap mail: printed in chat, no draft created (no recipients)` and carry that into Step 9. Otherwise, pack §5 shape via schemas §7: TL;DR → 回顧支柱 (counts) → 結構性問題 → 策略主軸 (each tagged 還在摸索 / 已定案) → nice-to-have → 專案盤點 (count · L1 split · P0–P3 counts if the room decided, else 「尚未評」 · owner table only from a tracker that has owners, else 「待認領」) → 下一步:三件事 → 附: 請與會者確認 + tracker link. Create it with `mcp__google-workspace__draft_gmail_message(user_google_email="peter_tu@zynkr.ai", to="<the addresses the user named as ONE comma-separated string, e.g. teammate-a@example.com, teammate-b@example.com>", subject="[<cycle> planning] 回顧+專案盤點 recap(YYYY-MM-DD)", body=<zh-TW body>, body_format="plain")` and confirm a `Draft ID` came back. `to` is a single string field — join several recipients with `, `; never pass a list. The subject is this skill's house default (pack §5 gives the body shape, not a subject line) — use the user's wording when they give one. Hard rule 6: never send. ### Step 9 — Report what was written and what was not Print: cycle · tracker ID (created by this run / existing / builder-fresh — say which) + per-tab URLs written (or "not written — awaiting confirmation") · counts (原文行數 → 正規化 items · rulings by verb · 中/低 readings · 做得好 / 可加強 · 覆蓋缺口 LOBs) · where the item list lives (chat / `⑤ 正規化清單` / `.md` ID) · draft ID + recipients (or "recap printed in chat, no draft — no recipients") · conditional rulings awaiting ②#n · an explicit **did-not** list: SOR tab untouched (unless told; empty for the builder's `fill` mode), no owners / priorities / dates assigned, mail not sent, speakers not named, LOBs not filled. Then name the next command: `/planning-tracker-builder <tracker ID>`. Then stop. --- ## Outputs - Main Tracker tabs (new or existing; versioned by new tab on re-run): `README` · `<cycle> 回顧總結` (5 重點結論 + retro rows) · `② 白板原文` · `③ 去重與歸類決策` · `④ MECE 檢查`. - The normalized item list (`主類別 · 子類別 · 項目(正規化)· 出處 · 信心`) for `/planning-tracker-builder` — in the chat by default, plus a `.md` in the hub folder written only after confirmation; a `⑤ 正規化清單` tab is an optional extra outside pack §6, on request only; written into `<cycle> 專案項目` only on request. A tracker created by this run leaves the SOR + pivot tabs empty for the builder's `fill` mode. - The `請與會者確認` list and the coverage-gap lines (README + chat). - A recap-mail Gmail DRAFT, never sent; a closing report of IDs / URLs + the did-not list. ## Reference files - `./references/planning-knowledge-pack.md` — shared family pack (taxonomy §2 · priority §3 · runbook + recap shape §5 · tracker layout §6 · rulings §7 · versioning §8 · never-do §9). Do not edit here. - `./references/planning-sources.md` — shared live IDs (hub folder, tracker + gids, transcript, photos, LOB plan Docs, evidence sources). Do not edit here. - `./references/tracker-tab-schemas.md` — this skill's write contract: header rows, layouts, 領域 list, worked example rows, README keys, handoff shape, recap skeleton. ## Limitations - Handwriting is read by a vision pass, not OCR — dense or oblique photos lower 判讀信心; the answer is the `請與會者確認` list, not a guess. Per-column full-resolution crops are mandatory (Step 1); pen colour can itself be uncertain (`藍/黑`, 判讀信心 中). - The transcript is raw ASR: normalise (spaces, homophones, 原句 kept) before segmenting; a Part-1-only transcript yields no `逐字稿裡的決策`. Rulings that hinge on a 中/低 reading are conditional (`(待確認 ②#n)`) until the room confirms. - Speaker attribution from an unlabelled block is heuristic; without a user-supplied map every retro row stays 未標示 and no quote is credited to a person. - Uses the pack §2 default L2 set; a cycle that renames L2 rows must say so (L1 numbers never change). Coverage gaps are flagged with plan-Doc quotes, never filled. - Writes only the working tabs + README; owners, 重要×緊急, priorities, dates, pivot and SOR lint belong to `planning-tracker-builder`; weekly follow-up to `planning-tracker-sync`. No calendar or 1:1 artefact is touched; the mail is drafted only. ## House style Writing style is **not owned by this file**. The house voice lives in two Google Docs under `[@] 寫作指南` (`12DBdFz3SK22ie9im_ThFMI7IBRXsTZsV`), read at runtime: - 《[2.0] Zynkr 通用風格指南 House Voice》 `10bOIQwRm9Pxwgct4hlwCwK_B4Pipai1HqBPZKzyRHSE` — the universal core, plus the addendum for this surface - 《[3.2] 禁用詞清單 Forbidden Words》 `1N5sHLP4qzmmhpCGsi6KElxi1z0MFe4QZ0Q_35T10Uyg` Read both before producing client- or reader-facing text, and scan the draft against 《[3.2]》 before handing it over. If Drive is unreachable, say so in the output rather than proceeding unchecked. Never re-implement either list inside this file.