| name | training-process-video |
| sheetId | 4.02 |
| description | Post-process a livestream transcript into four parallel workstreams: an event recap Google Doc, a Q&A knowledge base diff, course lecture note proposals, and marketing content idea seeds. |
| category | training |
| project | training-process-video |
| platform | claude |
| status | Done |
| author | Peter Tu |
| input | Raw livestream transcript text and a stream-config.md file identifying the training stream |
| process | 4 parallel agents — event recap doc, Q&A knowledge base update, course outline enhancement, and content idea curation |
| output | Google Doc recap, Q&A diff entries, lecture note proposals, and content idea seeds |
| synergy | [] |
Process Livestream
Orchestrate four parallel agents to transform a livestream transcript into reusable course content, a knowledge base update, a published recap document, and new content ideas for the marketing pipeline.
Step 0 — Stream selection
Scan the subdirectories of <your-training-design-root>/ for folders that contain a stream-config.md file. Each such folder is an available training stream.
Display:
─────────────────────────────────────────
選擇訓練串流
─────────────────────────────────────────
請選擇此逐字稿所屬的訓練串流:
1️⃣ [folder name of first match]
2️⃣ [folder name of second match]
3️⃣ [folder name of third match]
(依掃描結果列出,數量不固定)
─────────────────────────────────────────
Wait for the user to type a number.
After selection:
- Store the absolute path to the selected stream directory as
STREAM_DIR (e.g., <your-training-design-root>/4.4 claude-code-for-operation)
- Read
[STREAM_DIR]/stream-config.md to load all stream configuration
- From the config, extract and store:
course_outline: filename of the course outline file (e.g., 4.4.1 course.md)
chapter_prefix: prefix used for chapter files (e.g., claude-code-ops)
chapter_count: total number of chapter files
recap_folder_id: Google Drive folder ID for recap uploads
roster_folder_id: Google Drive folder ID for participant roster Sheets (TODO = skip Gate F)
roster_input_folder_id: Google Drive folder ID where a shortcut to the roster Sheet is created for GAS aggregation (TODO = skip shortcut creation)
kit_tag_prefix: Kit tag prefix for this stream, e.g. [4] Claude Code (TODO = skip Gate F.5)
- All Google Doc/Sheet IDs listed in the Google Workspace Sync Map section of the config
Display: ✅ 已載入串流設定:[selected stream folder name]
Step 1 — Collect inputs
Ask the user for:
- Transcript file path: path to the transcript
.md file (can be anywhere on disk)
- Stream title: short name for this session (e.g., "Claude Code 營運直播 no.1")
- Stream date: YYYY-MM-DD format (default: today's date if not provided)
Step 1a — Transcript intake (always runs)
The transcript file was already loaded into context by the user (via @file reference). This step only handles renaming and path storage — no file reading required.
Compute standardized filename:
- Take
stream_title, convert to lowercase
- Replace spaces and special characters with hyphens; remove consecutive hyphens
- Append
-[stream_date].cleaned.md
- Format:
[slug]-[YYYY-MM-DD].cleaned.md
Determine what action is needed:
Store the resulting absolute path as FILE_PATH and the filename as FILE_NAME for use in Step 10.
If the rename or copy fails, display the error and stop.
Display:
✅ 逐字稿就緒
原始檔案:[source_file_path]
標準化名稱:[FILE_NAME]
Step 2 — Pre-flight check
Before launching agents, display:
─────────────────────────────────────────
直播後製 — 準備啟動
─────────────────────────────────────────
Stream : [title]
Date : [date]
Length : [N] words / approx. [M] minutes of reading
─────────────────────────────────────────
將啟動 4 個平行 Agent:
[1] Event Recap → 回顧文章草稿(需審核後上傳 Google Drive)
[2] Q&A KB → Diff 報告(需審核後寫入)
[3] Course Enhancer → 講義提案(需審核後寫入)
[4] Content Curator → 內容點子提案(需審核後寫入 _matrix.md)
─────────────────────────────────────────
所有寫入與上傳均在審核後執行,不會自動發布。
繼續? [Y/n]
Wait for confirmation. If the user types n or no, stop.
Google Workspace Sync Map
After human approval at each gate, approved local file changes are also pushed to their corresponding Google Workspace documents. Use <your-google-workspace-account> as user_google_email for all MCP calls.
Read the Google Workspace Sync Map from [STREAM_DIR]/stream-config.md. Use the Doc/Sheet IDs listed there for all sync operations.
If any ID is TODO, skip that sync and note it in the summary.
Sync procedure (applies to Gates A, B, C, D):
- Write approved content to the local file first.
- Read the full updated local file.
- Use
mcp__google-workspace__get_doc_content to get the current Google Doc content.
- Use
mcp__google-workspace__batch_update_doc to replace the Google Doc body with the full updated local file content (delete existing text from index 1 to end, then insert at index 1).
- For the Content Matrix Google Sheet (Gate D), use
mcp__google-workspace__modify_sheet_values to append new rows to the appropriate sheet tab.
- If any MCP sync call fails, report the error but do not block the workflow — the local file is the source of truth.
Step 3 — Read reference files
Before launching agents, read the following files so their contents are available to pass to agents:
[FILE_PATH] (the transcript — use this as transcript input for all agents)
[STREAM_DIR]/knowledge-base/qa-master.md (KB contents for Agent 2)
[STREAM_DIR]/[course_outline from config] (course outline for Agent 3)
[STREAM_DIR]/[chapter_prefix from config]-ch1.md through [STREAM_DIR]/[chapter_prefix from config]-ch[chapter_count].md (chapter files for Agent 3)
[STREAM_DIR]/content-matrix/_matrix.md (content matrix for Agent 4)
If any chapter file is missing, note it and pass an empty string for that chapter.
If _matrix.md cannot be read, note it and Agent 4 will treat all ideas as NEW.
If [STREAM_DIR]/knowledge-base/qa-master.md does not exist, prompt:
─────────────────────────────────────────
⚠️ 找不到 knowledge-base/qa-master.md
─────────────────────────────────────────
[B] Bootstrap — 依章節分類架構建立空白 qa-master.md(從 stream-config.md 讀取章節 taxonomy)
[S] 略過 Agent 2(本次執行不執行 Q&A 知識庫更新)
─────────────────────────────────────────
Wait for user input.
- [B]: Create
[STREAM_DIR]/knowledge-base/qa-master.md with chapter taxonomy headers as defined in stream-config.md. Then proceed with Agent 2 normally.
- [S]: Skip Agent 2 entirely for this run. Set its status to
⏭ 已略過 on the status board.
Step 4 — Launch 4 agents in parallel
Launch all four agents simultaneously using the Task tool. Show the status board immediately after launching:
─────────────────────────────────────────
Agent 狀態板
─────────────────────────────────────────
[1] Event Recap ⏳ 執行中...
[2] Q&A KB ⏳ 執行中...
[3] Course Enhancer ⏳ 執行中...
[4] Content Curator ⏳ 執行中...
─────────────────────────────────────────
Agent 1 — Event Recap
Instruction to agent (pass as prompt):
- Read
agents/training-event-recap.md for your full instructions
- Inputs: transcript text, title, date
- Do NOT call any MCP tools — return formatted content only
- Return the structured result block described in your instructions
Agent 2 — Q&A Knowledge Base
Instruction to agent (pass as prompt):
- Read
agents/training-qa-knowledge.md for your full instructions
- Inputs: transcript text, full contents of
[STREAM_DIR]/knowledge-base/qa-master.md
- Local file reads only — no MCP writes
- Return the diff report described in your instructions
Agent 3 — Course Outline Enhancer
Instruction to agent (pass as prompt):
- Read
agents/training-outline-enhancer.md for your full instructions
- Inputs: transcript text, course outline (
[STREAM_DIR]/[course_outline from config]), all chapter files ([STREAM_DIR]/[chapter_prefix]-ch1.md through [STREAM_DIR]/[chapter_prefix]-ch[chapter_count].md)
- Local file reads only — no MCP writes
- Return the match report described in your instructions
Agent 4 — Content Idea Curator
Instruction to agent (pass as prompt):
- Read
agents/training-idea-curator.md for your full instructions
- Inputs: transcript text, stream title, stream date, full contents of
[STREAM_DIR]/content-matrix/_matrix.md
- Local file reads only — no MCP writes
- Return the idea report described in your instructions
Step 5 — Collect results and update status board
As each agent completes, update the status board:
─────────────────────────────────────────
Agent 狀態板
─────────────────────────────────────────
[1] Event Recap ✅ 完成 — 草稿已備妥,待審核上傳
[2] Q&A KB ✅ 完成 — [N] 筆新增,[M] 筆重複
[3] Course Enhancer ✅ 完成 — [K] 段符合,[J] 段未匹配
[4] Content Curator ✅ 完成 — [L] 個點子符合,[P] 個略過
─────────────────────────────────────────
If any agent returned an error, show it clearly and continue with the remaining agents.
After all four complete (or fail), display a 1-paragraph plain-text summary for each.
Step 6 — Gate A: Q&A Knowledge Base write
Display the MECE health check from Agent 2 first:
─────────────────────────────────────────
Gate A — MECE 健檢
─────────────────────────────────────────
[Display the full MECE HEALTH CHECK block from Agent 2]
─────────────────────────────────────────
If any MECE flags exist (CATEGORY_MISMATCH, OVERLAP_RISK, CATEGORY_BLOAT, ORPHAN_CATEGORY), prompt:
⚠️ 發現 [N] 個 MECE 問題,建議在寫入前處理。
[F] 逐筆修正(逐一顯示每個問題,讓你決定接受建議或略過)
[I] 忽略,直接進入寫入審核
Wait for user input. If [F]:
- For each flag, show the issue and the agent's suggestion. User types
y to accept the suggested fix (update category / skip entry / merge), n to keep as-is.
Then display the full diff report and show:
─────────────────────────────────────────
Gate A — Q&A 知識庫寫入審核
─────────────────────────────────────────
新增:[N] 筆 | Variant:[M] 筆 | 衝突:[K] 筆
(重複項目已自動略過)
[A] 全部寫入新增項目
[S] 逐筆選擇
[N] 略過,不寫入
─────────────────────────────────────────
Wait for user input.
- [A]: Insert all NEW entries into
[STREAM_DIR]/knowledge-base/qa-master.md at their specified insert_after positions (the KB is ordered by chapter → topic; do NOT append to the end). If a new topic group is needed, add a <!-- Topic: [name] --> comment before the first entry in the group. For VARIANT and CONTRADICTS entries, ask separately: "是否更新現有 KB 條目?[Y/n]"
- [S]: Show each NEW entry one at a time (including its
insert_after position). User types y to include, n to skip. After cycling through NEW entries, handle VARIANT/CONTRADICTS the same way.
- [N]: Skip all writes for Gate A.
After writing (if any), show: 已寫入 [N] 筆到 knowledge-base/qa-master.md
Google Sync: If any entries were written to [STREAM_DIR]/knowledge-base/qa-master.md, sync the full updated file to the QA Master KB Google Doc using the ID from stream-config.md and the sync procedure described in the Google Workspace Sync Map section. Show: ☁️ 已同步至 Google Doc(QA Master KB)
Step 7 — Gate B: Lecture notes write
Display the match report from Agent 3, grouped by target chapter file.
Then show:
─────────────────────────────────────────
Gate B — 講義提案審核
─────────────────────────────────────────
符合段落:[N] 段,分布於 [K] 個章節檔案
[A] 全部寫入
[S] 逐段選擇
[N] 略過,不寫入
─────────────────────────────────────────
Wait for user input.
- [A]: Append all qualifying lecture note blocks to their respective chapter files.
- [S]: Show each proposal one at a time. User types
y to append, n to skip.
- [N]: Skip all writes for Gate B.
For each approved block, append to the end of the correct chapter file ([STREAM_DIR]/[chapter_prefix]-ch[N].md).
After writing (if any), show: 已寫入 [N] 段到 [K] 個章節檔案
Google Sync: For each chapter file that was modified, sync the full updated file to its corresponding Google Doc using the sync procedure and IDs from stream-config.md. Show: ☁️ 已同步 [K] 個章節至 Google Docs
Step 8 — Gate C: Unmatched content
If Agent 3 returned any unmatched segments, display them now:
─────────────────────────────────────────
Gate C — 未匹配內容處理
─────────────────────────────────────────
以下 [N] 段內容未能匹配現有課程章節:
For each unmatched segment, show it and prompt:
[段落描述]
Agent 建議:[add to outline / skip]
[1] 加入課程大綱(會標記在 [course_outline from config] 的建議清單)
[2] 加入章節檔末尾(選擇章節)
[3] 略過
Wait for user to type 1, 2, or 3.
- [1]: Append a note to
[STREAM_DIR]/[course_outline from config] at the end under a ## 直播內容建議 section (create if not exists).
- [2]: Ask which chapter, then append as a brief note at the end of that chapter file (
[STREAM_DIR]/[chapter_prefix]-ch[N].md).
- [3]: Do nothing.
Google Sync: After all unmatched segments are processed, sync any modified files to their corresponding Google Docs using the sync procedure and IDs from stream-config.md. This may include [course_outline from config] and/or chapter files. Show: ☁️ 已同步未匹配內容至 Google Docs
Step 9 — Gate D: Content idea matrix write
If Agent 4 returned no qualifying ideas, skip this gate.
Otherwise, display the full idea report from Agent 4.
Then show:
─────────────────────────────────────────
Gate D — 內容點子寫入審核
─────────────────────────────────────────
符合提案:[N] 個 | 低分略過:[M] 個 | 重複略過:[K] 個
目標檔案:[STREAM_DIR]/content-matrix/_matrix.md
重複略過明細:
- [pain summary] → 與 [existing-id] (global_index [NNN]) 重複
- ...
低分略過明細:
- [pain summary] | [X]/8 | 未通過:[failed checks]
- ...
[A] 全部寫入符合提案
[S] 逐筆選擇
[N] 略過,不寫入
─────────────────────────────────────────
Wait for user input.
- [A]: Append all qualifying seed rows to
[STREAM_DIR]/content-matrix/_matrix.md under the correct category table. Also append a new session entry to [STREAM_DIR]/content-matrix/_sourcing-log.md documenting this run: date, stream title, method "livestream transcript", count of ideas added.
- [S]: Show each proposal one at a time. User types
y to include, n to skip. After all selections, write approved rows and log the session.
- [N]: Skip all writes for Gate D.
When appending to [STREAM_DIR]/content-matrix/_matrix.md:
- Add each approved row to the correct category table (prompt / skills / subagents / mcp / cot)
- Assign the
global_index sequentially, incrementing from the current highest value in the matrix
- Update the Status Summary table at the bottom: increment
seed count by the number of rows added, update Last updated date
When appending to [STREAM_DIR]/content-matrix/_sourcing-log.md:
- Add a new session block under
## Sessions, newest first:
### [YYYY-MM-DD] — [Stream Title]
**Method:** Livestream transcript
**Duration:** —
**Ideas added to matrix:** [N] ([list of IDs added])
**Validation runs:** 0 (all remain `seed`)
**Notes:** Extracted by training-idea-curator agent via /training-process-video.
After writing (if any), show: 已寫入 [N] 筆到 _matrix.md,並更新 _sourcing-log.md
Google Sync: If any ideas were written to _matrix.md, also sync to the Content Matrix Google Sheet and sourcing-log sheet using the IDs from stream-config.md.
Matrix sheet (use the Content Matrix Sheet ID and sheet name matrix from stream-config.md):
- If the sheet has no header row, first write the header row to
matrix!A1:K1:
| A | B | C | D | E | F | G | H | I | J | K |
|---|
| global_index | id | category | pain_point_raw | pain_resonance_score | solution_type | result_claim | status | file_path | sourced_from | notes |
- Append each approved seed row to the next empty row using
mcp__google-workspace__modify_sheet_values with range matrix!A[next_row]:K[next_row].
Sourcing-log sheet (use the same Content Matrix Sheet ID with sheet name sourcing-log from stream-config.md):
- If the sheet has no header row, first write the header row to
sourcing-log!A1:F1:
| A | B | C | D | E | F |
|---|
| date | stream_title | method | ideas_added | idea_ids | notes |
- Append a session row with: date, stream title, "livestream transcript", count of ideas, comma-separated list of IDs, "Extracted by training-idea-curator agent via /training-process-video."
Show: ☁️ 已同步 [N] 筆至 Google Sheet(Content Matrix + Sourcing Log)
Step 9.5 — Gate E: Event Recap upload to Google Drive
If Agent 1 returned an error, skip this gate and note it in Step 10.
Otherwise, display the full formatted recap content from Agent 1 for review.
Then show:
─────────────────────────────────────────
Gate E — 活動回顧上傳審核
─────────────────────────────────────────
標題:[DOC_TITLE]
(以上為即將建立的 Google Doc 內容)
[Y] 確認上傳 Google Drive
[E] 編輯後再上傳(請直接修改上方內容並回覆 Y)
[N] 略過,不上傳
─────────────────────────────────────────
Wait for user input.
- [Y]: First, save a local copy of the approved recap content to
[STREAM_DIR]/[YYYY-MM-DD]-course-recap.md. Then, read recap_folder_id from stream-config.md. If it is TODO, skip the Google Drive upload step and note it in the summary. Otherwise, create the Google Doc and move it to the recap folder using MCP:
- Write the approved recap content to
[STREAM_DIR]/[YYYY-MM-DD]-course-recap.md
mcp__google-workspace__create_doc — title: [DOC_TITLE]
mcp__google-workspace__batch_update_doc — insert the approved content into the document body
- If
recap_folder_id is not TODO: mcp__google-workspace__update_drive_file — move the doc to the recap folder by setting add_parents: [recap_folder_id] and remove_parents: root
mcp__google-workspace__get_drive_shareable_link — retrieve shareable URL
Store the URL as RECAP_DOC_URL and the local path as RECAP_LOCAL_PATH for use in Step 10.
Show: ✅ 本地檔案:[RECAP_LOCAL_PATH] and ✅ Google Doc 已建立並移至回顧資料夾:[RECAP_DOC_URL]
- [E]: Wait for the user to provide edited content, then proceed as [Y] with the revised text.
- [N]: Skip upload and local save. Set
RECAP_DOC_URL to "(略過)" and RECAP_LOCAL_PATH to "(略過)".
Step 9.6 — Gate F: Participant roster upload
This step handles the .xlsx participant roster downloaded from the event platform (e.g. Accupass/活動通). Accupass has no API — the user downloads the file manually and provides the path.
Read roster_folder_id from stream-config.md. If it is TODO, skip this gate, set ROSTER_STATUS to "略過(未設定 roster_folder_id)" and proceed to Step 9.7.
If no participant list path was provided in Step 1, ask:
─────────────────────────────────────────
Gate F — 參加名單歸檔
─────────────────────────────────────────
請提供活動平台下載的 .xlsx 檔案路徑:
(輸入路徑,或按 Enter 略過)
─────────────────────────────────────────
If user skips (empty Enter), set ROSTER_STATUS to "略過" and proceed to Step 9.7.
Otherwise, show:
─────────────────────────────────────────
Gate F — 參加名單歸檔
─────────────────────────────────────────
來源檔案:[xlsx 路徑]
上傳目標:[活動名稱]_[YYYY.M.DD](Google Sheet)
目標資料夾:[roster_folder_id 對應資料夾]
[若 roster_input_folder_id 已設定] 同時建立捷徑至 input 資料夾(供 GAS 更新總表用)
[Y] 確認上傳
[N] 略過
─────────────────────────────────────────
[Y] — execute (use Python + Drive API; MCP has no xlsx→Sheet conversion tool):
-
Upload the xlsx and convert it to a Google Sheet in the roster_folder_id folder:
from googleapiclient.http import MediaFileUpload
media = MediaFileUpload(xlsx_path,
mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
resumable=True)
file_meta = {
'name': '[活動名稱]_[YYYY.M.DD]',
'mimeType': 'application/vnd.google-apps.spreadsheet',
'parents': ['[roster_folder_id]']
}
sheet = drive_service.files().create(body=file_meta, media_body=media, fields='id,webViewLink').execute()
SHEET_ID = sheet['id']
-
If roster_input_folder_id in stream-config.md is not TODO, create a shortcut in that input folder (one per event):
shortcut_meta = {
'name': '[活動名稱]_[YYYY.M.DD]',
'mimeType': 'application/vnd.google-apps.shortcut',
'shortcutDetails': {'targetId': SHEET_ID},
'parents': ['[roster_input_folder_id]']
}
drive_service.files().create(body=shortcut_meta, fields='id').execute()
-
Set ROSTER_STATUS to "✅ 已上傳並建立捷徑"
Show:
✅ 參加名單已上傳為 Google Sheet:[webViewLink]
✅ 捷徑已建立至 input 資料夾(供 GAS 使用)
[N]: Set ROSTER_STATUS to "略過"
Step 9.7 — Gate F.5: Upload subscribers to Kit
If ROSTER_STATUS is "略過" (Gate F was skipped), skip this gate and set KIT_STATUS to "略過".
Read kit_tag_prefix from stream-config.md (e.g. [4] Claude Code). If it is TODO, skip this gate and set KIT_STATUS to "略過(未設定 kit_tag_prefix)".
Otherwise, display:
─────────────────────────────────────────
Gate F.5 — 上傳訂閱者至 Kit
─────────────────────────────────────────
來源:參加名單 Google Sheet([SHEET_ID])
動作:新增至 Kit 訂閱者列表 + 打上活動標籤
[Y] 確認執行
[N] 略過
─────────────────────────────────────────
[N]: Set KIT_STATUS to "略過", proceed to Step 10.
[Y] — execute:
1. Read the roster
Read SHEET_ID with mcp__google-workspace__get_drive_file_content to get the CSV content.
Column mapping (Accupass format):
- Column index 2: 訂購人姓名 → Kit
first_name
- Column index 3: 訂購人Email → Kit
email_address
2. Clean the data
- Dedupe: keep the first row per email
- Filter: skip emails containing
privaterelay.appleid.com (Apple private relay — undeliverable)
Display the cleaning result: 原始 N 筆 → 去重 X 筆 → 過濾 Y 筆 → 有效 Z 筆
3. Resolve the Kit tag
Use mcp__kit__list_tags to find the highest number among tags sharing the kit_tag_prefix, then +1 for the new tag number. Create it with mcp__kit__create_tag (returns the existing ID if the tag already exists).
4. Bulk-create subscribers
Call mcp__kit__bulk_create_subscribers in batches of ≤100 (upsert — existing subscribers are updated automatically).
Collect every valid subscriber_id — including those returned inside "Cannot override state" failure items. Those subscribers already exist and must still be tagged, otherwise they are silently missed.
5. Bulk-tag subscribers
Call mcp__kit__bulk_tag_subscribers in batches of ≤100 with the tag from step 3.
Set KIT_STATUS to "✅ [N] 筆已上傳,標籤:[tag_name]"
Show:
✅ Kit 訂閱者已更新:[N] 筆成功 | [M] 筆失敗
🏷 標籤:[tag_name](ID: [tag_id])
Step 10 — Final summary and file archival
Display:
─────────────────────────────────────────
✅ Process Livestream 完成
─────────────────────────────────────────
Stream : [title] ([date])
📄 活動回顧
本地檔案:[RECAP_LOCAL_PATH]
Google Doc:[RECAP_DOC_URL]
🗂 Q&A 知識庫
寫入:[N] 筆新增 | 更新:[M] 筆 Variant | 略過:[K] 筆
☁️ Google Sync:[成功/略過/失敗]
📚 課程講義
寫入:[N] 段 → [list of chapter files modified]
未匹配處理:[N] 段加入大綱建議 | [M] 段略過
☁️ Google Sync:[K] 個文件已同步 / [失敗清單]
💡 內容點子
寫入:[N] 個 seed → _matrix.md | 略過:[M] 個
☁️ Google Sync:[成功/略過/失敗]
📋 參加名單
[ROSTER_STATUS]
📧 Kit 訂閱者
[KIT_STATUS]
─────────────────────────────────────────
After displaying the summary, call agents/training-doc-admin.md with:
action: move
file_path: the FILE_PATH stored from Step 1a
processed_transcript_dir: [STREAM_DIR]/processed-transcript/
Display the result:
- On success:
📁 逐字稿已移至 processed-transcript/[FILE_NAME]
- On error: surface the error message from the agent
Error Handling
- If the admin agent returns
blocked or error during transcript intake, stop the entire workflow — there is no transcript to process.
- If Agent 1 (Event Recap) returns an error, skip Gate E and note it in the final summary.
- If Agent 2 returns no Q&A pairs, skip Gate A entirely.
- If Agent 3 returns no qualifying segments, skip Gate B. Still run Gate C if unmatched segments exist.
- If a chapter file write fails, report the specific file and continue with others.
- If Agent 4 returns no qualifying ideas, skip Gate D entirely.
- If
_matrix.md cannot be written, report the error — do not attempt to write _sourcing-log.md either.
- If any MCP call in Gate E fails, show the error and offer to retry or skip.
- Never silently swallow errors — always surface them in the status board.