建立專案時,使用者通常還不知道 Agent 第一輪會提出什麼方案。如果一開始就要求填入「第二輪要修改的內容」,還沒看過草案就得決定要改什麼。
DAY 22 把資料搬進 MySQL 後,今天想調整的是建立專案的順序:先用自然語言收集需求、執行第一輪,等 PM 草案出來,再讓使用者決定要直接定稿,還是提出修改進入第二輪。
在 .env 設定 PROJECT_INTAKE_CHANNEL_ID 後,Bot 只在指定頻道處理建案訊息。「我要做一個網站」這類明確句型直接進入資料收集;其他說法交給本機 Qwen 判斷是否想建立專案。未設定時入口不啟用,其他頻道與既有指令也不受影響。
PROJECT_INTAKE_CHANNEL_ID=填入指定頻道的 ID

框起來的是拿取ID的地方。
bot.py 用 on_message listener 接收訊息。下面只節錄入口的篩選條件:沒有設定頻道、訊息來自其他頻道或 Bot,或內容是原本的指令,就不交給專案收集流程。
@bot.listen("on_message")
async def project_intake_message(message: discord.Message) -> None:
if (not settings.project_intake_channel_id
or message.guild is None
or message.channel.id != settings.project_intake_channel_id
or message.author.bot
or message.content.strip().startswith(("!", "/"))):
return
這裡使用 listener,沒有覆蓋原本的指令處理。Bot 也必須啟用 Message Content Intent,才能讀取一般訊息的內容。
固定句型以外的訊息,新增的 ProjectIntentAgent 只負責判斷意圖,不會直接建立專案。它回傳 create_project、not_project 或 uncertain,並附上名稱、信心值與理由。只有判定為 create_project 且信心值至少 0.8,Bot 才會請使用者先確認理解的專案名稱,再收集後續資料;判斷不明確、格式有誤或模型逾時,就改回覆固定範例,不硬開新專案。
進入收集流程後,Bot 會逐項詢問尚缺的專案名稱、類型、需求、預算、期限和驗收條件。模型判斷的名稱會先請使用者確認;完整資料也要再回覆「確認」,Bot 才會建立專案。資料確認前可以回覆「取消」。草稿依 Guild、頻道和使用者分開保存,避免不同對話互相覆蓋。


專案入口的訊息會出現在指定頻道。不要在需求中輸入密碼或其他敏感資料。
確認專案資料後,Bot 會建立專案、執行第一輪 Agent 討論,並顯示 PM 草案。此時使用者可以選擇:
第二輪變更因此是使用者看過草案後提出的需求,不必在專案建立前預先假設。
bot.py 的兩條路徑,簡化後大致如下。這段省略了輸入檢查、中斷重試和 Discord 訊息回覆;完整流程仍以專案程式碼為準。
if content == "直接定稿":
await finalize_intake(message.guild.id, message.channel)
elif content.startswith("修改:") or content.startswith("修改:"):
separator = ":" if ":" in content else ":"
description = content.split(separator, 1)[1].strip()
change = await resolve_repository_result(
add_change(message.guild.id, session.project_id, description)
)
await discussion_manager.start_second_round(message.guild.id, change)
await display_intake_draft(message.guild.id, message.channel)
await finalize_intake(message.guild.id, message.channel)
差別在於 add_change():只有使用者真的提出修改,才會保存需求變更並執行第二輪。直接定稿會略過這一步。




PM 草案現在可以根據一輪或兩輪內容產生。如果使用者先看過第一輪草案,之後才提出修改,系統會讓舊草案快取失效,等第二輪完成後再重新整合。Review 仍負責審查最終草案,最多執行一次 Agent 修改。
確認專案後,Bot 會從這個 Discord 伺服器的工作區讀取預設優先目標。管理員可用 /priority 在「成長」、「成本效益」、「品牌影響」和「創新」之間選擇;/workspace 則能查看目前專案和成果數。
第一個 Agent 執行前,會議會保存當下的優先目標,以及同 Guild、同類型專案最近三筆最終方案摘要。PM 和 Review 可以參考這些資料;若找不到歷史成果,就從空清單開始。管理員之後調整預設目標,也不會改掉已開始會議的依據。

自然語言入口建立的專案與會議資料保存在 MySQL。新增需求變更時,系統會檢查專案是否屬於目前 Guild、是否仍在進行中,以及是否已經使用過一次變更;沒有提出修改時,不會建立空的需求變更資料。
完整會議保存最終方案時,MySQL 會在同一筆交易將專案狀態設為 completed,並清除 Guild 的進行中專案索引。若只完成第一輪、尚未產生最終方案,專案不會提早釋放。最新會議索引與歷史紀錄則會保留。
若模型或流程中斷,入口會提示重試。已寫入 MySQL 的專案和會議不會因 Discord 訊息傳送失敗而刪除。
對話中的暫存階段仍放在 Bot 記憶體。Bot 重啟或對話閒置 30 分鐘後,尚未完成的對話階段會消失;已建立的專案與會議不受影響。若第一輪草案已保存但對話中斷,可以使用 /review 定稿。
.venv/bin/python -m unittest discover -s tests
Ran 108 tests ... OK (skipped=5)
.venv/bin/python -m py_compile ...
通過
git diff --check
通過
MySQL 定向整合測試也確認:未提出修改前不會建立需求變更;提出修改後才保存變更,且跨 Guild 修改會被拒絕。只有單輪討論時不會釋放進行中的專案;保存最終方案後,專案才會完成並釋放,讓同一 Guild 可以啟動下一個專案。測試使用專用 Guild 和專案,結束後已清理資料。
以上是原本入口的單元、語法與 MySQL 整合測試。加入意圖判斷後,實作報告記錄完整測試 122 項通過、5 項跳過;其中 16 項針對意圖判斷與入口流程。Discord 的實測則要分兩條路徑看。
固定句型入口已在 Discord 實際走通:從指定頻道輸入建案訊息、補齊資料,到顯示第一輪草案與最終結果。新增的模型路徑做過本機 Qwen 驗證;修正 title 欄位後,「我要開一間咖啡廳」可回傳 create_project,信心值 0.95。但修正版還沒記錄 Discord 重新驗收,不能把兩條路徑都寫成實機通過。
DAY 23 把「需求變更」放回看過草案之後,也讓入口能理解固定句型以外的建案說法。使用者先說需求、看第一輪結果,再決定要不要修改。現有圖片維持原位;模型路徑的 Discord 畫面,等重新驗收後再補。