VS Code Copilot Lifecycle Hooks — 設計文件¶
版本:v1.0 | 2025-03
對應 VS Code Copilot Hooks (Preview, v1.109.3+)
概述¶
MedPaper Assistant 透過 VS Code Copilot 的 8 個生命週期斷點 (Lifecycle Hook Events),在 Agent 對話過程中注入品質檢查、模式保護、記憶同步。這些 hooks 與我們既有的 76-check 架構(A/B/C/D/E/F/G/P/R 系列)協同運作。
核心設計原則¶
- Shell-Based:所有 hook 用 bash 實作,透過 stdin/stdout JSON 通訊
- Non-Blocking Default:大多數 hook 僅注入
additionalContext,不阻斷 Agent - State Sharing:hooks 間透過
.github/hooks/_state/目錄下的 JSON 檔案通訊 - Audit Trail:所有工具呼叫記錄至
_state/session_audit.jsonl
8 Event Lifecycle 對應表¶
| # | VS Code Event | 我們的 Hook | 腳本 | 功能 |
|---|---|---|---|---|
| 1 | SessionStart | session-init | session-init.sh |
讀取模式、恢復狀態、檢查 pending evolutions |
| 2 | UserPromptSubmit | prompt-analyzer | prompt-analyzer.sh |
偵測用戶意圖、注入工作流引導 |
| 3 | PreToolUse | pre-tool-guard | pre-tool-guard.sh |
模式保護、危險指令攔截、save_reference 規則 |
| 4 | PostToolUse | post-tool-check | post-tool-check.sh |
Writing hooks 觸發、引用提醒、審計記錄 |
| 5 | PreCompact | pre-compact-save | pre-compact-save.sh |
Context 壓縮前的記憶保存 |
| 6 | SubagentStart | subagent-init | subagent-init.sh |
注入專案/模式上下文至 subagent |
| 7 | SubagentStop | (不實作) | — | 不需要攔截 subagent 結束 |
| 8 | Stop | session-stop | session-stop.sh |
記憶同步提醒、審計結算、清理暫存 |
Hook 鏈路圖¶
┌──────────────────────────────────────────────────────────────────────┐
│ VS Code Copilot Session │
├──────────────────────────────────────────────────────────────────────┤
│ │
│ ① SessionStart │
│ └─ session-init.sh │
│ ├─ Read .copilot-mode.json → mode │
│ ├─ Read .mdpaper-state.json → recovery context │
│ ├─ Check pending-evolutions.yaml → improvement hints │
│ └─ Write _state/session_context.json → shared state │
│ │
│ ↓ (user types a prompt) │
│ │
│ ② UserPromptSubmit │
│ └─ prompt-analyzer.sh │
│ ├─ Detect intent: mode-switch / commit / writing / autopilot │
│ └─ Inject workflow guidance (SKILL.md reminder) │
│ │
│ ↓ (agent decides to use a tool) │
│ │
│ ③ PreToolUse ←──── GATE (can DENY or ASK) ────┐ │
│ └─ pre-tool-guard.sh │ │
│ ├─ Mode protection (normal/research → deny │ │
│ │ writes to .claude/ src/ tests/ etc.) │ │
│ ├─ Destructive cmd blocking (rm -rf, etc.) │ │
│ ├─ save_reference → warn use _mcp │ │
│ └─ Audit: log tool invocation │ │
│ │ │
│ ↓ (tool executes) │ │
│ │ Feedback │
│ ④ PostToolUse ──────────────────────────────────┘ Loop │
│ └─ post-tool-check.sh │
│ ├─ Draft edit → "run run_writing_hooks()" │
│ ├─ concept.md edit → "validate_concept() required" │
│ ├─ git commit → memory sync reminder │
│ ├─ save_reference → "get_available_citations()" │
│ └─ Audit: log tool completion │
│ │
│ ↓ (repeat ③→④ for each tool call) │
│ │
│ ⑤ PreCompact (when context gets too long) │
│ └─ pre-compact-save.sh │
│ ├─ Summarize: mode, doing, project, writing section │
│ └─ Inject: "call sync_workspace_state() before continuing" │
│ │
│ ⑥ SubagentStart (when subagent is spawned) │
│ └─ subagent-init.sh │
│ ├─ Inject active project + mode │
│ └─ Agent-specific guidance (reviewer=read-only, etc.) │
│ │
│ ⑧ Stop (session ends) │
│ └─ session-stop.sh │
│ ├─ Reminder: sync memory-bank, workspace state │
│ ├─ Write session_end to audit log │
│ └─ Clean up transient _state/session_context.json │
│ │
└──────────────────────────────────────────────────────────────────────┘
與 76-Check 架構的整合¶
PreToolUse × PostToolUse 循環(核心)¶
這兩個 hook 構成一個 回饋迴路,是我們 Code-Enforced 品質系統的入口:
PostToolUse (draft edited)
→ injects "run run_writing_hooks(hooks='post-write')"
→ Agent calls run_writing_hooks
→ PreToolUse allows (it's an MCP tool)
→ WritingHooksEngine executes A1-A6, A3b (34 checks)
→ PostToolUse captures result
→ Agent fixes issues if any
Hook 對應 Check 系列¶
| Lifecycle Hook | 觸發的 Check 系列 | 觸發方式 |
|---|---|---|
| PostToolUse (draft edit) | A1-A6, A3b (post-write) | 注入 additionalContext 提醒 agent 呼叫 run_writing_hooks |
| PostToolUse (section complete) | B1-B16 (post-section) | Agent 依 SKILL.md 呼叫 run_writing_hooks(hooks='post-section') |
| PostToolUse (manuscript done) | C1-C13 (post-manuscript) | Agent 依 SKILL.md 呼叫 |
| PreToolUse (git commit) | P1-P8, G1-G9 (pre-commit) | Agent 載入 git-precommit SKILL.md 執行 |
| Stop | Memory sync | 注入提醒更新 memory-bank/ |
| SubagentStart (reviewer) | E1-E5 (EQUATOR) | 注入上下文至 reviewer subagent |
非 Lifecycle 的 Checks(由 SKILL.md 指導)¶
| Check 系列 | 觸發時機 | 機制 |
|---|---|---|
| D1-D9 (Meta-Learning) | Phase 10 | Agent 依 auto-paper SKILL.md 呼叫 run_meta_learning |
| F1-F4 (Data Artifacts) | post-manuscript | Agent 依 SKILL.md 呼叫 validate_data_artifacts |
| R1-R6 (Review Hooks) | Phase 7 submit | Agent 依 SKILL.md 呼叫 submit_review_round → ReviewHooksEngine |
State File 通訊¶
.github/hooks/_state/
├── session_context.json # SessionStart 寫入,其他 hook 讀取
│ └─ { mode, doing, next_action, active_project, writing_session, ... }
└── session_audit.jsonl # 所有 hook 追加寫入
└─ { timestamp, event, tool, ... } (一行一筆 JSON)
生命週期:
session_context.json:SessionStart 建立 → PreToolUse/SubagentStart 讀取 → Stop 刪除session_audit.jsonl:全程追加 → Stop 寫入結算 → 保留供審計
Hook I/O 規格¶
共通輸入(stdin JSON)¶
所有 hooks 都會收到:
{
"tool_name": "...", // PreToolUse, PostToolUse
"tool_input": {...}, // PreToolUse
"tool_result": "...", // PostToolUse
"userMessage": "...", // UserPromptSubmit
"agentName": "..." // SubagentStart
}
輸出格式¶
| Hook | 可用輸出欄位 | 說明 |
|---|---|---|
| PreToolUse | permissionDecision (allow/deny/ask) |
控制工具是否執行 |
| PreToolUse | permissionDecisionReason |
向 Agent 解釋原因 |
| PreToolUse | updatedInput |
修改工具輸入參數 |
| PreToolUse | additionalContext |
注入上下文 |
| PostToolUse | decision (block) |
阻斷結果傳回 Agent |
| PostToolUse | additionalContext |
注入上下文 |
| 其他 | additionalContext |
注入上下文 |
配置檔案¶
位置:.github/hooks/mdpaper-lifecycle.json
{
"version": 1,
"hooks": {
"SessionStart": [{ "type": "command", "command": "...", "timeout": 10 }],
"UserPromptSubmit": [{ "type": "command", "command": "...", "timeout": 5 }],
"PreToolUse": [{ "type": "command", "command": "...", "timeout": 5 }],
"PostToolUse": [{ "type": "command", "command": "...", "timeout": 15 }],
"PreCompact": [{ "type": "command", "command": "...", "timeout": 10 }],
"SubagentStart": [{ "type": "command", "command": "...", "timeout": 5 }],
"Stop": [{ "type": "command", "command": "...", "timeout": 10 }]
}
}
Timeout 設計:
- 5s:輕量 hook(prompt-analyzer, pre-tool-guard, subagent-init)
- 10s:中量 hook(session-init, pre-compact-save, session-stop)
- 15s:重量 hook(post-tool-check,可能需要讀取多個狀態檔案)
與 pubmed-search-mcp 的 Hooks 比較¶
| 特性 | pubmed-search-mcp | mdpaper (本專案) |
|---|---|---|
| 範圍 | 單一 MCP 服務的 pipeline 控管 | 整個 workspace 生命週期 |
| Events | 5 (session, prompt, preTool, postTool, sessionEnd) | 7 (+ PreCompact, SubagentStart) |
| 策略 | Pipeline 強制、結果評估 | 模式保護、品質 Hook 觸發、記憶管理 |
| State | workflow tracker + session context | session context + audit trail |
| 跨平台 | sh + ps1 | 僅 sh(Linux/macOS) |
安全考量¶
- PreToolUse deny 是硬閘——Agent 無法繞過被 deny 的工具呼叫
- Exit code 2 = blocking error,防止 hook 腳本錯誤影響 Agent 運行
- Mode protection 確保研究人員不會意外修改框架核心代碼
- Destructive command pattern 使用白名單式檢查(只攔截已知危險模式)
- State 目錄 不含敏感資料,僅有模式和工具名稱
- .gitignore 應排除
_state/目錄(暫存資料)
依賴¶
- jq — 必要的 JSON 處理工具。若未安裝,所有 hook 會自動降級(exit 0 = 全部放行)
- 安裝:
sudo apt install jq(Ubuntu) /brew install jq(macOS) - bash — 4.0+ (Linux/macOS 內建)
未來擴展¶
- Windows 支援:為每個 .sh 建立對應 .ps1(參考 pubmed-search-mcp)
- SubagentStop:如需監控 subagent 輸出品質
- PreToolUse updatedInput:自動修正工具參數(如自動補全 project slug)
- PostToolUse decision: block:攔截低品質工具輸出(目前未使用)
- Multi-hook 串聯:同一事件可配置多個 hook 依序執行