feat: 薄殼原則落地 + seed 下沉 API + MCP 進主庫 + 部署一致性

壓測四橫向問題修正(docs 壓測報告):

① 薄殼原則成鐵律:能力長在 API,CLI/MCP/lib 只暴露
   - seed 下沉成 API 行為:cypher-executor POST /init/seed(一次灌 API+auth recipe),
     種子資料移到 server src/lib/api-recipe-seeds.ts,CLI 改薄殼一次呼叫
   - 解除 deployFullyOk 連坐 + init 補 seed auth recipe + update 補 seed/全 KV
   - registry SUBMISSIONS_KV 補進 REQUIRED_KV_NAMESPACES(修 20/21)

② MCP 統一帳號來源(單一 remote MCP + .env 切 MCP URL)
   - MCP 從 sibling repo 搬進 arcrun/mcp/(remote Worker,route 改 mcp.arcrun.dev)
   - config 加 mcp_url 三層解析 + getMcpUrl + DEFAULT_MCP_URL
   - 新增 acr mcp-setup:依 config 寫專案 .mcp.json(接案切資料夾自動切 MCP)
   - acr --version 改動態讀 package.json(根治漂移)

③ Deploy 一致性
   - tests/release.feature + scripts/check-release.sh
   - local-deploy.sh:CLI npm publish + auto patch bump + CHANGELOG
   - local-deploy.sh bash 3.2 相容修正(mapfile / 空陣列 set -u)
   - builtins/pnpm-lock.yaml

④ README self-hosted 同步現況(移除 R2 殘留、加 flag/env、多帳號)

CLI bump → 1.3.0

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
uncle6me-web
2026-06-06 15:45:35 +08:00
parent 5f381a44a6
commit 3e65e22775
58 changed files with 8608 additions and 74 deletions
+147
View File
@@ -0,0 +1,147 @@
/**
* arcrun_report_feedback — explicit feedback tool for AI agents
*
* 對應 SDD .agents/specs/llm-interface/ M1.3
*
* AI agent 每次完成 workflow / 卡住 / 解掉問題後 **MUST** call 此 tool。
* 結構化 issue_type enum 防自由文字難聚合。寫入 KBDB type=agent-feedback block。
*
* 後續 M4 weekly_review workflow 聚合這些 block 產出 arcrun-roadmap。
*
* 命名注意:M5 全面 rename u6u → arcrun 前,本 tool 直接用新名 arcrun_ prefix
* 立下範例。其他 u6u_* tool 等 M5 一次切。
*/
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { Env } from "../types.js";
import { kbdbFetch } from "../lib/kbdb-client.js";
const ISSUE_TYPES = [
"success_story", // 順利完成,值得記錄這個 pattern
"doc_unclear", // AGENTS.md / skill / contract 講不清楚
"tool_missing", // 該有的 MCP tool 沒有
"error_unhelpful", // 錯誤訊息看不懂下一步
"unexpected_behavior", // 跟我預期的不一樣
"feature_request", // 我想要 X 功能
] as const;
export function registerReportFeedback(server: McpServer, env: Env, orgNamespace: string) {
server.tool(
"arcrun_report_feedback",
"AI agent 完成 workflow 任務 / 卡住 / 解掉問題後 **必須** call 此 tool 回報。即使順利也要 call (issue_type=success_story),那是告訴平台「這 pattern 已 work,可推廣」。回饋會寫進 KBDB type=agent-feedback,週報自動聚合產出平台改善 roadmap。",
{
issue_type: z.enum(ISSUE_TYPES).describe(
"回報類型。success_story=順利做完 / doc_unclear=文件不清楚 / tool_missing=該有的 MCP tool 缺 / error_unhelpful=錯誤訊息看不懂下一步 / unexpected_behavior=與預期不符 / feature_request=想要新功能"
),
description: z.string().min(10).describe(
"詳述:你做了什麼、發生什麼、為什麼這算 issue / story。至少 10 字。若是 success_story,描述 pattern 與適用情境"
),
workflow_name: z.string().optional().describe("相關 workflow 名稱(若有)"),
retry_count: z.number().int().min(0).optional().describe("為了搞定,你重試了幾次(含修 YAML / 改參數)"),
blocked: z.boolean().optional().describe("是否完全擋住(true = 無法繼續),預設 false"),
suggested_fix: z.string().optional().describe("你建議的修補方向(optional,但很有價值)"),
agent_user_agent: z.string().optional().describe(
"你(AI agent)的 client 識別字串。e.g. 'claude-code/1.x'、'cursor-mcp/0.4'、'mira-bot'。讓平台知道哪個 AI 客戶端踩到問題"
),
},
async ({ issue_type, description, workflow_name, retry_count, blocked, suggested_fix, agent_user_agent }) => {
try {
if (!env.KBDB) {
return { content: [{ type: "text", text: "Error: KBDB service binding unavailable" }], isError: true };
}
const blockBody = {
api_key: env.PLATFORM_API_KEY || undefined, // 若 platform key 在,聚集;否則用用戶 namespace
type: "agent-feedback",
source: "mcp-tool-call",
user_id: orgNamespace,
content: description,
metadata_json: JSON.stringify({
issue_type,
workflow_name,
retry_count,
blocked: blocked ?? false,
suggested_fix,
agent_user_agent,
reported_at: new Date().toISOString(),
}),
tags_json: JSON.stringify([
"agent-feedback",
`issue:${issue_type}`,
...(blocked ? ["blocked"] : []),
...(workflow_name ? [`wf:${workflow_name}`] : []),
]),
};
// 走 KBDB service binding(既有 pattern
const createResp = await kbdbFetch(env, `/blocks`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(blockBody),
});
if (!createResp.ok) {
const errBody = await createResp.text();
return {
content: [
{
type: "text",
text: JSON.stringify({
ok: false,
error_code: "kbdb_write_failed",
human_message: `回饋寫入 KBDB 失敗:HTTP ${createResp.status}`,
next_actions: [
"確認 KBDB 服務在線(試 https://kbdb-get.arcrun.dev/health",
"若持續失敗,可暫先在本地記下回饋,稍後重試",
],
detail: errBody.slice(0, 200),
}, null, 2),
},
],
isError: true,
};
}
const data = await createResp.json().catch(() => null);
return {
content: [
{
type: "text",
text: JSON.stringify({
ok: true,
data: {
reported: true,
issue_type,
block_id: (data as { id?: string } | null)?.id,
},
hints: [
issue_type === "success_story"
? "感謝記錄成功 pattern!這會被納入週報自動推廣。"
: "感謝回報!平台週報會聚合這類問題(M4 完成後可看 arcrun-roadmap block",
"若還有相關問題(例如同 workflow 不同 issue),可繼續 call",
],
}, null, 2),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: JSON.stringify({
ok: false,
error_code: "internal_error",
human_message: `report_feedback 內部錯誤:${error instanceof Error ? error.message : String(error)}`,
next_actions: ["重試一次", "若持續失敗,請告訴用戶這個 issue 並貼錯誤訊息給 leo"],
}, null, 2),
},
],
isError: true,
};
}
}
);
}