Skip to content

feat: 發布 v1.0.0 訪談 reasoner 基線#28

Draft
MakiDevelop wants to merge 48 commits into
mainfrom
feat/interview-reasoning
Draft

feat: 發布 v1.0.0 訪談 reasoner 基線#28
MakiDevelop wants to merge 48 commits into
mainfrom
feat/interview-reasoning

Conversation

@MakiDevelop
Copy link
Copy Markdown
Owner

Summary

  • ship the L2 interview reasoner path with real evidence extraction and coverage updates
  • add reviewable persona export flow, LINE dogfood controls, and v1.0.0 package metadata
  • extract high-value reasoner prompt details into private runtime configuration for open-core hygiene
  • add moat hygiene checks to keep v2 methodology assets and private exports out of the public repo

Moat Hygiene

This PR intentionally does not include v2 methodology assets, Bait-Reaction implementation, private domain packs, real interview transcripts, exported persona files, or private calibration data.

Validation

  • ./scripts/check_moat_hygiene.sh
  • .venv/bin/ruff check src tests
  • .venv/bin/python -m pytest -q (257 passed)
  • VPS deployment smoke: /healthz OK on feat/interview-reasoning at 4dbe461

Release Note

Public v1.0.0 should be positioned as a working open-source framework with baseline interview reasoning, coverage tracking, LINE dogfood controls, and reviewable export plumbing. It is not the full private 8-week deep extraction methodology.

Tag Note

The current v1.0.0 git tag points to 76d2977, before the moat prompt extraction commit 4dbe461. Retagging should be done only after the main merge target is final.

MakiDevelop and others added 30 commits May 18, 2026 10:59
開源框架、不開源方法論。v2 草稿(題庫/domain packs/引擎 spec/研究文件)+ 內部 roadmap docs/TRUNK.md 共 9 檔 git rm --cached(本機保留、停止追蹤)。v1 題庫保留作框架範本。

Constraint: 已 push 到公開 repo 的歷史收不回,本次僅止血未來追蹤。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
specs/10 對 docs/TRUNK.md(6 處)與 09-interview-engine-v2.md(1 處)的連結改為中性抽象描述(internal roadmap / internal methodology notes),不刪內容、不增內容。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
webhook_event_id 與 message_id 皆缺時,原本 fallback 用 id(event) 記憶體位址當 event id,導致 LINE 重送同一訊息去重失效。改為回 None、記 error log、skip 該事件。新增測試覆蓋 skip 路徑。

Directive: fail-closed — 無法去重的事件丟棄而非照處理,不冒重複處理風險
Not-tested: 完整 195 suite(repo 有 pre-existing WIP,留 L4 確認)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 清除 config.py 內部垃圾定義與重複欄位,恢復 Settings 可正常 import
- 在 process_turn 加入 reasoning_turn_enabled + REASONING_TEST_USER_IDS whitelist 早期返回
- MVP:whitelist 使用者走 TurnReasoner + Guardrail 產生的 reply
- 其餘使用者與 command/light_greeting/closing 路徑完全走舊邏輯(零影響)

L2 核心(prompt、few-shot、distrustful/soften/reflection 護欄)已就位,今日即可在自己 LINE 測試。

Refs: feat/interview-reasoning, L0 25a3dc1 之後的 L1/L2 接線
VPS 上的 .env 已存在 VIRTUALME_LINE_SNAPSHOT_EXPORT_ENABLED / USER_IDS,
加入對應 Field 避免 extra_forbidden 驗證錯誤。
這是部署相容性補丁,與 L2 推理無關。

feat/interview-reasoning
- 將硬編碼 claude-3-5-haiku-20241022 改為專案 MODEL_FAST (claude-haiku-4-5)
- 加上 ruff noqa 於 SYSTEM_PROMPT,讓中文標點不擋 lint

這應該解決用戶測試時遇到的 404 not_found_error。

feat/interview-reasoning
- whitelist 使用者現在會先存 user turn、再跑 reasoner
- 根據 next_move == ADVANCE 時真的切 current_question + record_asked
- 根據 HONOR_SKIP / EXPLICIT_REFUSAL 記 log(後續可擴)
- 支援 should_echo 預先附和
- 每輪都打詳細 [NEW REASONER] log(move / boundary / eng / next_q / echo / reflection),方便即時觀察是否還鬼打牆

這版應該能明顯減少「一直重問同一題」的問題。

feat/interview-reasoning
- 在重要原則新增:當受訪者不清楚要回答到什麼程度時,應主動用具體例子說明
- 在思考步驟第 3 步加入「評估受訪者是否清楚期望深度」
- 在步驟 8 加入「或用具體例子澄清」
- 新增 Example 5 few-shot:受訪者反問「你要什麼樣的SOP」時,用真實例子回應(直接示範好答案的樣子)

這是針對 Maki 實測反饋「不知道要回答到什麼程度」的直接修正。

feat/interview-reasoning
- 重要原則新增:經過多次互動後,若判斷繼續追問已無價值,應主動總結目前理解並詢問是否推進
- 思考步驟第 4 步強化:評估當前題完成度 + 繼續追問是否已無價值(主動總結並推進)
- 新增 Example 6 few-shot:受訪者多次以高層次回答回應,reasoner 主動總結『理解問題→解決問題』循環,並詢問是否要換方向或推進下一題

這是針對 Maki 實測反饋「不懂想要什麼 + 希望能自己做總結不要一直追」的直接修正,讓 reasoner 更有『訪談進度意識』。

feat/interview-reasoning
- 新增 progress_card.py 產生原生 Flex Message(八維 × 三層視覺進度)
- 在 process_turn 裡偵測「進度」「目前進度」「請問現在的訪談進度」等關鍵字
- transport/line.py 支援回傳 FlexMessage(不只純文字)
- 目前使用 realistic mock snapshot(以你測試中的 SKILL 進度為主)
- 支援用戶主動觸發,15 分鐘間隔主動建議的機制已預留

這是目前能做到的實際程度,可直接在 LINE Bot 測試。

feat/interview-reasoning
- 新增 get_progress_text_for_user,回傳格式化的八維三層文字進度
- process_turn 偵測到「進度」關鍵字時,直接回傳文字版
- 保留 Flex 程式碼,待 SDK 相容性修復後再切回

這次部署後,用戶打「進度」應該會看到實際的進度文字,而不是 fallback。
- 新增 LayerProgress / DimensionProgress / CoverageSnapshot 資料模型
- 在 build_turn_state 裡實作第一版真實計算(依 anchors + layer 分組 + 簡單 quality scoring)
- TurnState 現在會帶 coverage_snapshot,供 L2 reasoner 使用

這是 B 方向的第一步:讓進度從 mock 變成基於真實 DB anchors 的資料。

feat/interview-reasoning
- SYSTEM_PROMPT 新增 coverage 意識原則
- _build_user_prompt 輸出各維度真實層級收集狀態(淺/中/深 + quality)
- reasoner 現在可以根據 coverage 決定是否繼續 probe 或 advance

這是把 B(真實 CoverageSnapshot)真正接給 reasoner 的關鍵一步。

feat/interview-reasoning
…IPLE)

- 修正 _compute_coverage_snapshot 中的 order 比較
- 修正 turn_reasoner prompt building 中的 Layer 存取
- 現在 coverage_snapshot 應該可以正常運作,不會再 crash

feat/interview-reasoning
- 新增 render_progress_text(snapshot),直接從真實的 CoverageSnapshot 產生文字報告
- bot.py 的進度處理現在會呼叫 build_turn_state 取得真實 snapshot 再渲染
- 下次用戶打「進度」就會看到根據實際 anchors 計算的真實收集狀態

這完成了「先切」的承諾。

feat/interview-reasoning
- 中層進度會乘以淺層完成度(至少保留一點信用)
- 深層進度會乘以中層完成度
- 這樣可以避免「沒有淺層卻有中層/深層」的奇怪現象

這應該能解決用戶觀察到的「人際關係、日誌/日常 沒有淺層直接中層」的問題。

feat/interview-reasoning
- 新增最高優先原則:除非大多數維度的淺層已 sufficient,否則不應優先挖中層/深層
- 更新步驟 7:選擇下一題時,優先補淺層不足的維度
- 這是把「優先把淺層收集完」的規則正式落入 reasoner 決策

feat/interview-reasoning
- 新增「換維度勇氣」原則:當連續多輪集中在少數維度且資訊量低時,應主動換到其他維度的淺層
- 強化步驟 7:明確要求在選擇下一題時,檢查是否過度集中在少數維度,若是則強烈傾向換維度
- 目的是讓 reasoner 更有勇氣離開低價值區域,避免一直圍繞同一個面向(尤其是職涯)

feat/interview-reasoning
- 新增「低品質回應觸發機制」原則:連續兩輪低品質即主動忽略銜接,優先挑淺層最弱的維度
- 新增思考步驟 4.5:回答品質趨勢與換維度評估
- 強化步驟 7:低品質時忽略銜接,直接挑最弱淺層
- 調整 coverage_text 呈現,優先突出各維度淺層狀態

這是根據用戶「C>B>A」+「2輪連續低品質」+「純粹挑最弱淺層」的明確指示所做的 prompt 強化。

feat/interview-reasoning
- 新增「核心目標(最高優先)」:讓受訪者花的時間有產出 + 最終人格檔有價值
- 在思考步驟最前面加入常駐檢查:任何做法都要服務這兩個目標
- 所有既有原則(淺層優先、低品質觸發、換維度勇氣、環節長度控制)現在都明確服從於這兩個底層目標

這是把用戶最根本的期望(時間有產出、人格檔有價值)直接寫進 model 的最高層。

feat/interview-reasoning
MakiDevelop and others added 18 commits May 19, 2026 15:01
1. 不追問受訪者不想聊的
2. 聊天必須有明確的收集目的
3. 最終要系統性把八維三層(尤其是淺層)收集完整

這三點現在是整個 SYSTEM_PROMPT 的最高層,所有其他原則都必須服從。

feat/interview-reasoning
- 把「每一題都要有清楚的收集意圖(回收什麼特徵)」寫成強制要求
- 在思考步驟新增 6.5:選擇下一題前必須先想清楚收集目標
- 優化 coverage_text 呈現,特別突出「目前淺層最弱的前三個維度」,讓 model 更容易做出有目的的選擇
- 強調「不要為了聊天而問問題」

這是回應用戶「不要尬聊、每一題都要有目的性」的嚴格要求。

feat/interview-reasoning
- 新增強制步驟 0:每次決定下一步前,必須先明確想清楚這一題要回收哪個維度的哪一層、什麼特徵,以及為什麼這題比其他題更有價值。
- 這是為了徹底落實「每一題都要有清楚的收集目的」,避免 reasoner 再出現「為了聊天而問問題」的行為。
- 同時微調步驟 7,讓選擇下一題必須基於收集意圖。

feat/interview-reasoning
- 在思考步驟最前面強制要求先想清楚「這一輪要回收什麼特徵」,再看受訪者的回答。
- 強調「你不是聊天機器人,而是執行收集策略的訪談機器人」。
- 讓「不要為了聊天而問問題」成為最高層的約束。

這是為了真正落實用戶「每一題都要有清楚的收集目的」的嚴格要求。

feat/interview-reasoning
- 方便之後比對 Haiku 與 Sonnet 20 輪收集到的八維證據量
- 實驗結束後可移除或保留

feat/interview-reasoning
把先前散落於 TRUNK / specs/05 / milestone 的「謹慎、克制、有敬畏」立場
codify 為六條 Stability & Restraint Principles:

  P1 State-Trait Separation
  P2 Contradiction Preservation
  P3 Reflective Restraint
  P4 Multi-Session Pattern Validation
  P5 Self-Correction & Agency
  P6 Provenance, Confidence & Temporal Decay

直接事故 anchor 為 milestone.md #16(2026-05 pilot 中 bot 越過受訪者明
說的情緒邊界)。本文件補上「同意之後的克制機制」,與 specs/05 互補
(specs/05 管 PII / informed consent 底線;本文件管 extraction /
synthesis / export 中的人格克制)。

M1 hard gate 鎖 P3+P5+P1+P4 四條最小門檻;P2 完整 schema、P6 完整
metadata、P4 完整 quorum 排 M2。

七位一體 council 證據鏈:~/Documents/agent-council/virtualme/SYNTHESIS.md
(5 agent answers + Architect synthesis + 67 學術引用)

Constraint: 六條為總上限,不擴張為 8+,控制憲法認知負擔
Rejected: 把 P6 拆成 P6+P7(Provenance vs Temporal Decay)| 收斂為一條 metadata 原則更直覺
Directive: P3 在 trauma-relevant context 不 honor reflection 即使使用者主動邀請 — 防 #16 重演
Not-tested: M1 hard gate 為文字 ratify,實作 contract test 屬 L1+ session

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
對應 specs/11-constitution.md §P3 M1 Hard Gate 第 4 條「probe cap 到達時
必須 stop / advance 並記 reason metadata」與第 3 條「reflection_note
預設 internal-only」的兩個 deterministic 部分。

Changes:
- turn_reasoner_schema.py / turn_reasoner.py: 新增 SkipStopReason enum
  (none / refusal / reluctance / fatigue / probe_cap_reached) + 同步加
  skip_stop_reason field 到 plain class 與 dataclass 兩個 TurnReasonerOutput
- guardrail.py: 抽 _replace_output() helper 同時支援 plain class 與
  dataclass;五個 fork 路徑都寫入對應 skip_stop_reason
- test_p3_reflective_restraint.py: 新增 6 個 contract test
  - explicit_refusal → HONOR_SKIP + reason=refusal
  - strong_reluctance + probe → SOFTEN + reason=reluctance
  - fatigued + probe → SOFTEN + reason=fatigue
  - probe cap reached → ADVANCE + reason=probe_cap_reached
  - no fork → default reason=none
  - reflection_note 不外洩進 reply

Verify: pytest 三檔(test_p3_reflective_restraint / test_turn_reasoner_prompt
/ test_turn_state)共 15 passed in 0.49s

Council 委派證據鏈:~/Documents/agent-council/virtualme/codex-p3-briefing.md
+ codex-p3-answer.md

Constraint: 200 line diff cap(實際 148 行);不動 BASELINE_SYSTEM_PROMPT
Rejected: 統一 schema 與 dataclass 定義 | 保留兩處讓 import 鏈穩定,diff 更小
Directive: SkipStopReason 為封閉 enum,未來新 fork 需顯式加 enum + 更新 helper
Not-tested: 真實 LLM 訪談時 reflection_note 是否真會被 prompt 引去 reply(需 dogfood)

Co-Authored-By: Codex (gpt-5.4) <noreply@openai.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
對應 specs/11-constitution.md §P5 M1 Hard Gate 四條中的兩條 deterministic 部分:
hedge wording validator(第 1 條)+ unlike_me 阻擋 promotion 的 regression test
(第 2 條,既有 snapshot/core.py 已實作,本 commit 加 contract test 證實不退化)。

Changes:
- snapshot/hedge_validator.py: NEW,66 行
  - find_unhedged_assertions(): 偵測 8 條禁止 pattern(中英文)
    forbidden 含 "You are X" / "Your true self is" / "you always|never" /
    "你是 X 的人" / "你的本質是" / "你的真實面是" / "你總是 X"
  - has_hedge_marker(): 12 條 hedge markers
    含 "目前觀察到" / "tentative" / "draft" / "hypothesis" / "傾向" / "在 W" 等
  - HedgeViolation frozen dataclass

- tests/unit/test_p5_self_correction_agency.py: NEW,145 行,10 個 contract test
  - Category 1(hedge validator 單元測): 6 個 test 覆蓋中英文 forbidden + hedged
  - Category 2(unlike_me regression): 2 個 test 證實
    confidence_level → insufficient + policy_status → contradicted
  - Category 3(rebuttal entrypoint smoke): 2 個 test 證實
    restart_* commands 與 ReviewVerdict 4 個值不退化

Verify: pytest test_p5 + test_snapshot 共 29 passed in 0.49s(10 P5 + 19 既有
snapshot regression 全綠,證明 ConstructCard / unlike_me 邏輯沒被破壞)

Council 委派證據:~/Documents/agent-council/virtualme/codex-p5-{briefing,answer}.md

Constraint: 250 line diff cap(實際 211 行);不動 _finalize_construct_card 邏輯
Rejected: 立即實作 persona_corrections table | 排 M2,本 session 只做 hedge validator + regression
Directive: hedge validator 為 surface-level pattern 偵測,不是語義分析;未來新斷言句型需擴 FORBIDDEN_PATTERNS
Not-tested: export pipeline 整合 hedge enforcement gate(M2 工程;本 session 只交付 validator 工具)

Co-Authored-By: Codex (gpt-5.4) <noreply@openai.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
對應 specs/11-constitution.md §P1 M1 Hard Gate 第 1 條:synthesis / export 階段,
所有 Dimension.STATE 來源 anchor 不得 render 為 SOUL/VOICE/SKILL/BOUNDARIES
Core Truths。

Changes:
- snapshot/stability_gate.py: NEW,35 行
  - CORE_TRUTH_DIMENSIONS = frozenset({SOUL, VOICE, SKILL, BOUNDARIES})
    (STATE / HISTORY / JOURNAL / PEOPLE 預設不在此集合,M2 可擴)
  - is_eligible_for_core_truths(anchor): dimension != STATE → True
  - filter_core_truth_candidates(anchors): 批次過濾

- tests/unit/test_p1_state_trait_separation.py: NEW,120 行
  - Unit: CORE_TRUTH_DIMENSIONS membership / is_eligible / filter
  - Regression: STATE anchor「最近很累」不出現於 SOUL.md Core Truths section
  - Smoke: STATE.md 仍 export 不誤殺

Verify: pytest test_p1 + test_snapshot + test_export 共 34 passed in 0.45s
(既有 snapshot + export regression 全綠)

Council 委派證據:~/Documents/agent-council/virtualme/codex-p1-{briefing,answer}.md

Constraint: 200 line diff cap(實際 155 行);不在 _render_dimension_file 插 gate call
Rejected: 加 stability_kind field 到 Anchor schema | M2 才動 schema,M1 只交付 dimension-level gate
Directive: is_eligible_for_core_truths 為 dimension-only 判斷;M2 整合會在 _render_dimension_file / render_soul_lite 呼叫
Not-tested: cross-dimension projection(如 STATE anchor 透過 hypothesis 被 SOUL-lite 引用)— 留 M2

Co-Authored-By: Codex (gpt-5.4) <noreply@openai.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…n v1.1)

對應 specs/11-constitution.md §P4 M1 Hard Gate 第 1 條 + 第 3 條:single-session
來源 anchor 路徑禁止標 validated;contract test 覆蓋「3 個來自同一 session 的
anchor 即使 question_id 不同,不得進入 validated」。

第 2 條 hedge wording 已由 P5 commit c6a5bc0 (hedge_validator) 工具化。

Changes:
- snapshot/multi_session_validator.py: NEW,62 行
  - unique_session_count(db, turn_ids): 查 turns.session_id distinct count
  - is_single_session(db, anchor): 包裝
  - can_be_validated(db, anchor): P4 hard gate detector — 單場 session 一律 False

- tests/unit/test_p4_multi_session_validation.py: NEW,129 行,8 個 contract test
  - Unit: empty / same session × 3 / cross session × 2
  - is_single_session: same vs cross
  - can_be_validated: negative + positive
  - **Gap-surfacing regression**: 3 question_id 全部在同一 session 的 PRINCIPLE anchor
    既有 save_anchor 行為仍會設 triangulated=True(line 957 未查 session),
    但 can_be_validated 必須回 False — 文件化 M1→M2 gap

Verify: pytest test_p4 + test_snapshot + test_triangulation 共 37 passed in 0.47s

至此 Constitution v1.1 §M1 Hard Gate 全套 4 條落地:
  P1 (2d4bab5) State-Trait Separation — stability_gate
  P3 (2b68857) Reflective Restraint — skip_stop_reason + Guardrail metadata
  P4 (本 commit) Multi-Session Validation — multi_session_validator
  P5 (c6a5bc0) Self-Correction & Agency — hedge_validator + unlike_me regression

Council 委派證據:~/Documents/agent-council/virtualme/codex-p4-{briefing,answer}.md

Constraint: 200 line diff cap(實際 191 行);不修 save_anchor triangulation logic
Rejected: 立即 wire promotion gate 進 build_snapshot_bundle | M2 才整合,M1 只交付 detector
Directive: gap-surfacing test 故意保留「triangulated=True 但 can_be_validated=False」斷言,
           作為 M2 修 save_anchor session-aware triangulation 的 anchor
Not-tested: build_snapshot_bundle 與 export pipeline 是否真的會把 can_be_validated=False
            的 anchor 標為 validated(M2 整合時補 end-to-end test)

Co-Authored-By: Codex (gpt-5.4) <noreply@openai.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
pyproject.toml + README banner 從 1.0.0 升 1.1.0;新增 v1.1.0 Highlights 段落
中英文同步,含 Constitution v1.1 連結、reasoner refactor、persona 下載、4
條 M1 hard gate detectors(115 contract tests)。

明白標示 M2 範圍未做:detector wire 進 build_snapshot_bundle / export pipeline
是 M2 工作;v1.1.0 只交付 detector + contract test 鎖 invariant。

Tag v1.1.0 留給 Maki 於 PR #28 合進 main 後再手動下,避免在 feature branch
打 release tag。

Constraint: README highlights 段保持精簡(每條 1 line);不為 detector 補 user-facing 文案
Rejected: 直接打 v1.1.0 tag | 等 PR 合 main 後 Maki 手動 tag,避免 tag 指向 feat branch
Directive: README highlights 段落結構(- Constitution / - reasoning refactor / - persona download / - hard gates)為 v1.x 系列標準格式

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant