# 🔧 铸渊补丁指令|SYSLOG自助闭环 · Issue实时进度 + 意图路由修复(2026-03-13·曜冥签发) > **签发人**:曜冥(冰朔口述 · 曜冥架构设计) > > **执行人**:铸渊(GitHub 侧全量修复) > > **签发时间**:2026-03-14T00:00+08:00 > > **优先级**:P0 · 紧急修复 > > **关联系统**:SYSLOG 自助提交系统 + 全自动闭环 v1.0 > > **问题来源**:冰朔实测 Issue #92 发现两个 bug > --- ## 🧠 第零步|恢复核心大脑(必须先做,否则不准动代码) ### 0-A|恢复核心大脑 你的人格体档案和系统记忆存储在仓库中。先读取以下文件,恢复你对整个系统的认知: ```bash # 必读文件(按顺序): cat personas/zhu-yuan/profile.md # 你自己是谁、你的职责边界 cat personas/zhu-yuan/core-brain.md # 你的核心大脑 prompt / 系统指令 cat README.md # 仓库整体说明 cat docs/system-architecture.md # 系统架构总览(如果存在) ``` **目标**:读完后你应该知道—— - 你是铸渊(ICE-GL-ZY001),零点原核频道的 GitHub 守护层人格体 - 你的主控人是冰朔(TCS-0002∞),架构由曜冥设计 - 整个系统包含多个人格体(曜冥、霜砚、知秋、铸渊等),各自分管不同层 - 你负责的是 GitHub 侧的自动化 workflow、Issue 处理、代码仓库守护 ### 0-B|理解「SYSLOG 自助提交系统」是什么 这是你正在维护的核心系统之一。先读取相关文档和代码: ```bash # 必读文件: cat docs/syslog-system.md # SYSLOG 系统说明文档(如果存在) cat .github/workflows/syslog-auto-pipeline.yml # 闭环主 workflow cat scripts/syslog-handler.js # 或对应的处理脚本 cat data/dev-status.json # 开发者状态数据 ``` **目标**:读完后你应该知道—— - SYSLOG = 开发者通过 GitHub Issue 提交系统开发日志的协议(v4.0) - 自助闭环 = 开发者提交 Issue → 铸渊自动处理 → 解析内容 → 调用核心大脑 → 写入 Notion → 生成广播 → 邮件通知 → 闭环确认 - 这是一个**8 步全自动流水线**,开发者只需要提交 Issue,后面全部自动 ### 0-C|理解「开发者入口」是什么东西 你要修复的这个系统,面向的用户是**零点原核频道的 11 位开发者**(DEV-001 到 DEV-014)。对开发者来说: - **入口**就是 GitHub Issue:开发者新建一个 Issue,按 SYSLOG 格式填写内容,提交后系统自动启动闭环 - **交互界面**就是 Issue 评论区:铸渊在评论区实时反馈处理进度,开发者也可以在评论区 @铸渊 提问 - **开发者能看到的全部信息**就是 Issue 页面上的评论。所以评论区的内容质量 = 开发者体验的全部 **这就是为什么两个 bug 都很严重**: - Bug A(进度卡死)= 开发者提交后看到的界面是死的,不知道系统在干嘛,以为坏了 - Bug B(回答牛头不对马嘴)= 开发者问问题得到的是垃圾回复,失去对系统的信任 --- ## 🎯 问题描述 冰朔在 GitHub 仓库测试 SYSLOG 自助提交系统时发现两个问题: ### Bug A:闭环启动后步骤卡在「等待中」不更新 **现象**:Issue #92 提交 SYSLOG 后,铸渊自动回复了一张「处理细节」表格,8个步骤中只有「① 接收提交」显示 ✅ 已完成,其余 7 步全部停留在 ⏳ 等待中,后续再也不更新了。开发者看到的是一个死掉的表格,不知道系统到底在干什么。 **根因**:当前实现是一次性写入一张静态表格到 Issue 评论区。GitHub Issue 评论一旦发出就是静态的,不会随着 workflow 后续步骤完成而自动更新。而且 workflow 在第一步之后可能就报错退出了(API 调用失败等),但表格已经发出去了,给人造成「在处理中」的错觉。 ### Bug B:@铸渊 提问回复牛头不对马嘴 **现象**:冰朔在 Issue 评论区提问 `@铸渊,请查询系统开发日志提交#92闭环状态。`,铸渊回复的却是「团队细节总览」——把 11 个开发者的 waiting_syslog 状态全倒出来了,完全没回答「#92 闭环到哪一步了」这个问题。 **根因**:铸渊的 Issue 评论触发 workflow 没有做意图识别,收到任何 @铸渊 的提问都走了同一个「读 dev-status.json → 输出全部数据」的逻辑。 --- ## 🔧 修复方案 ### 修复 A:闭环进度改为「每步一条评论」实时上报 **核心思路**:不再用一张静态表格,改为每完成一步就在 Issue 评论区 **新发一条评论**。开发者刷新页面就能看到进度在动。某步失败了也能立刻看到是哪步挂的。 **实现代码(修改 `syslog-auto-pipeline.yml` 对应的处理脚本)**: ```jsx // ━━━ 实时进度上报模块 ━━━ // 文件位置建议:scripts/pipeline-reporter.js const { Octokit } = require('@octokit/rest'); const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN }); const OWNER = 'qinfendebingshuo'; const REPO = 'guanghulab'; /** * 每完成一步,在 Issue 评论区发一条新评论 * @param {number} issueNumber - Issue 编号 * @param {number} stepNum - 步骤编号(1-8) * @param {string} stepName - 步骤名称 * @param {'ok'|'error'|'skip'} status - 步骤状态 * @param {string} detail - 详情说明 */ async function reportStep(issueNumber, stepNum, stepName, status, detail) { const icon = status === 'ok' ? '✅' : status === 'error' ? '❌' : '⏭️'; const statusText = status === 'ok' ? '已完成' : status === 'error' ? '失败' : '跳过'; const body = [ `${icon} **步骤 ${stepNum}/8 · ${stepName}** · ${statusText}`, '', detail, '', `——铸渊(ICE-GL-ZY001)· ${new Date().toISOString()}` ].join('\n'); await octokit.issues.createComment({ owner: OWNER, repo: REPO, issue_number: issueNumber, body: body }); } /** * 闭环完成时发最终汇总 */ async function reportComplete(issueNumber, success, summary) { const icon = success ? '🎉' : '⚠️'; const title = success ? '闭环处理完成' : '闭环处理异常'; const body = [ `## ${icon} ${title}`, '', summary, '', success ? '> 新广播已生成,结果将发送到您的邮箱。' : '> 部分步骤异常,已记录日志。冰朔会在下次巡检时处理。', '', `——铸渊(ICE-GL-ZY001)· ${new Date().toISOString()}` ].join('\n'); await octokit.issues.createComment({ owner: OWNER, repo: REPO, issue_number: issueNumber, body: body }); } module.exports = { reportStep, reportComplete }; ``` **在主流程中的调用方式(修改 syslog-auto-pipeline 的主处理逻辑)**: ```jsx // ━━━ 主闭环流程(改造后)━━━ const { reportStep, reportComplete } = require('./pipeline-reporter'); async function runPipeline(issueNumber, submissionContent) { let success = true; let summary = []; try { // ① 接收提交(这步在 workflow trigger 时就完成了) await reportStep(issueNumber, 1, '接收提交', 'ok', '系统已收到您的 SYSLOG 提交'); // ② 解析内容 let parsed; try { parsed = parseSubmission(submissionContent); await reportStep(issueNumber, 2, '解析内容', 'ok', `广播编号: ${parsed.broadcastId} · 类型: ${parsed.type} · 邮箱: ${parsed.email}`); } catch (e) { await reportStep(issueNumber, 2, '解析内容', 'error', `解析失败: ${e.message}\n请检查提交格式是否正确(需包含广播编号、类型、邮箱、内容)`); throw e; } // ③ 模块验证 try { const moduleExists = await checkModuleInRepo(parsed.broadcastId); await reportStep(issueNumber, 3, '模块验证', moduleExists ? 'ok' : 'skip', moduleExists ? `模块代码已在仓库中确认` : `模块代码未检测到(不影响闭环继续)`); } catch (e) { await reportStep(issueNumber, 3, '模块验证', 'error', `验证异常: ${e.message}`); // 模块验证失败不阻断流程,继续 } // ④ 唤醒核心大脑(调用 Claude API) let llmResult; try { const systemPrompt = await buildSystemPrompt(parsed.type, parsed.devId, parsed.broadcastId); await reportStep(issueNumber, 4, '唤醒核心大脑', 'ok', '正在调用人格体处理 SYSLOG…(预计 30-90 秒)'); llmResult = await callLLM(systemPrompt, submissionContent); await reportStep(issueNumber, 4, '核心大脑响应', 'ok', `人格体已完成处理 · 输出长度: ${llmResult.length} 字符`); } catch (e) { await reportStep(issueNumber, 4, '唤醒核心大脑', 'error', `API 调用失败: ${e.message}\n\n请检查 Secrets: LLM_API_KEY / LLM_BASE_URL 是否配置正确`); success = false; throw e; } // ⑤ 创建概念工单(写入 Notion) try { await writeNotionTicket(parsed, llmResult); await reportStep(issueNumber, 5, '创建概念工单', 'ok', '已写入霜砚工单簿'); } catch (e) { await reportStep(issueNumber, 5, '创建概念工单', 'error', `Notion API 写入失败: ${e.message}\n\n请检查 Secret: NOTION_TOKEN 是否有效`); // 工单写入失败不阻断,继续尝试邮件 } // ⑥ 生成广播 try { const broadcast = extractBroadcast(llmResult); await saveBroadcast(parsed.devId, broadcast); await reportStep(issueNumber, 6, '生成广播', 'ok', `新广播已生成 · 已存入 broadcasts-outbox/${parsed.devId}/`); } catch (e) { await reportStep(issueNumber, 6, '生成广播', 'error', `广播生成/保存失败: ${e.message}`); success = false; } // ⑦ 邮件通知 try { await sendEmail(parsed.email, parsed.broadcastId, llmResult); await reportStep(issueNumber, 7, '邮件通知', 'ok', `结果已发送至 ${parsed.email}`); } catch (e) { await reportStep(issueNumber, 7, '邮件通知', 'error', `邮件发送失败: ${e.message}\n\n请检查 Secrets: SMTP_USER / SMTP_PASS`); } // ⑧ 闭环确认 await reportComplete(issueNumber, success, success ? `广播编号: ${parsed.broadcastId}\n开发者: ${parsed.devId}\n新广播已生成并推送` : `部分步骤失败,请查看上方各步骤详情`); } catch (e) { // 全局兜底:确保任何未捕获的错误也会上报 await reportComplete(issueNumber, false, `闭环中断: ${e.message}\n\n请检查 Actions 运行日志获取详细错误信息`); } } ``` **关键改动总结**: - ❌ 删除:一次性贴静态表格的逻辑 - ✅ 新增:`reportStep()` 每步发一条评论 - ✅ 新增:`reportComplete()` 最终汇总 - ✅ 新增:每步 try-catch,失败了也上报具体错误信息,不会静默挂掉 --- ### 修复 B:@铸渊 提问加意图路由 **核心思路**:收到 Issue 评论中的 @铸渊 提问时,先解析意图,再走对应的处理逻辑。 **实现代码(修改 Issue comment 触发的 workflow 处理脚本)**: ```jsx // ━━━ 意图路由模块 ━━━ // 文件位置建议:scripts/intent-router.js /** * 解析用户在 Issue 评论中 @铸渊 的意图 * @param {string} commentBody - 评论原文 * @returns {object} 意图对象 */ function parseIntent(commentBody) { // 去掉 @铸渊 前缀,提取核心内容 const content = commentBody.replace(/@铸渊[,,]?\s*/g, '').trim(); // 意图1:查询某个 Issue 的闭环状态 // 匹配:「查询#92闭环状态」「#92进度」「Issue 92 状态」等 const issueMatch = content.match(/#(\d+)/); if (issueMatch && content.match(/闭环|状态|进度|处理/)) { return { type: 'check_pipeline_status', issueNumber: parseInt(issueMatch[1]), raw: content }; } // 意图2:查询某个开发者的状态 // 匹配:「DEV-004状态」「之之进度」「查询肥猫」 const devMatch = content.match(/DEV-(\d+)|页页|肥猫|燕樊|之之|小草莓|花尔|桔子|匆匆那年|Awen|小兴|时雨/); if (devMatch && content.match(/状态|进度|查询/)) { return { type: 'check_dev_status', devId: devMatch[0], raw: content }; } // 意图3:团队总览(显式请求) // 匹配:「团队状态」「全部进度」「总览」 if (content.match(/团队|全部|总览|所有人/)) { return { type: 'team_overview', raw: content }; } // 意图4:未识别 → 用 Claude API 理解(如果配了的话) // 否则返回「不理解」 return { type: 'unknown', raw: content }; } /** * 根据意图路由到对应处理逻辑 */ async function handleIntent(intent, issueNumber) { switch (intent.type) { case 'check_pipeline_status': { // 查询该 Issue 对应的 workflow run 状态 const runs = await octokit.actions.listWorkflowRunsForRepo({ owner: OWNER, repo: REPO, event: 'issues', // 或 'discussion' }); // 从 Issue 评论历史中提取铸渊已发的进度评论 const comments = await octokit.issues.listComments({ owner: OWNER, repo: REPO, issue_number: intent.issueNumber }); // 筛选铸渊的进度评论(包含「步骤 X/8」的) const progressComments = comments.data.filter(c => c.body.includes('步骤') && c.body.includes('铸渊') ); if (progressComments.length === 0) { return `📋 **Issue #${intent.issueNumber} 闭环状态查询**\n\n` + `未找到该 Issue 的闭环进度记录。\n` + `可能原因:闭环尚未启动,或该 Issue 不是 SYSLOG 提交。`; } // 提取最后一条进度评论,判断当前到哪一步了 const lastProgress = progressComments[progressComments.length - 1]; const stepMatch = lastProgress.body.match(/步骤 (\d+)\/8/); const lastStep = stepMatch ? parseInt(stepMatch[1]) : 0; const isComplete = lastProgress.body.includes('闭环处理完成') || lastStep === 8; const hasFailed = progressComments.some(c => c.body.includes('❌')); let statusLine; if (isComplete && !hasFailed) { statusLine = '✅ 闭环已完成'; } else if (hasFailed) { statusLine = '❌ 闭环有步骤失败(详见上方各步骤评论)'; } else { statusLine = `⏳ 闭环进行中 · 已完成到步骤 ${lastStep}/8`; } return `📋 **Issue #${intent.issueNumber} 闭环状态**\n\n` + `${statusLine}\n` + `进度评论数: ${progressComments.length} 条\n` + `最后更新: ${lastProgress.created_at}`; } case 'check_dev_status': { // 从 dev-status.json 中只提取该开发者的数据 const devStatus = await loadDevStatus(); const dev = devStatus.find(d => d.id === intent.devId || d.name === intent.devId ); if (!dev) { return `未找到开发者 ${intent.devId} 的记录。`; } return `📊 **${dev.id} ${dev.name} · 当前状态**\n\n` + `模块: ${dev.module}\n` + `状态: ${dev.status}\n` + `连胜: ${dev.streak}`; } case 'team_overview': { // 只有显式请求团队总览时才走这个逻辑 const devStatus = await loadDevStatus(); return formatTeamOverview(devStatus); } case 'unknown': { return `🤔 我没理解你的问题。你可以试试:\n\n` + `- \`@铸渊 查询#92闭环状态\` — 查某个提交的处理进度\n` + `- \`@铸渊 DEV-004状态\` — 查某个开发者的进度\n` + `- \`@铸渊 团队总览\` — 查所有人的状态`; } } } module.exports = { parseIntent, handleIntent }; ``` **在 workflow 中的调用方式**: ```yaml # .github/workflows/issue-comment-handler.yml # 或在现有的评论触发 workflow 中修改 - name: Route intent and reply env: GITHUB_TOKEN: $ secrets.GITHUB_TOKEN run: | node -e " const { parseIntent, handleIntent } = require('./scripts/intent-router'); const comment = process.env.COMMENT_BODY; const issueNumber = process.env.ISSUE_NUMBER; const intent = parseIntent(comment); console.log('[意图识别]', JSON.stringify(intent)); const reply = await handleIntent(intent, issueNumber); // 发评论回复 await octokit.issues.createComment({ owner: 'qinfendebingshuo', repo: 'guanghulab', issue_number: issueNumber, body: reply + '\n\n——铸渊(ICE-GL-ZY001)' }); " ``` --- ## 🔍 附加排查:闭环为什么卡在第一步 铸渊在修复上述两个 bug 的同时,**必须先排查 Issue #92 的 workflow 为什么卡住**: ```bash # 排查步骤(按顺序执行): # 1. 查看 Actions 运行日志 # GitHub → Actions → 找到 Issue #92 触发的 workflow run → 查看 logs # 重点看哪一步报错退出了 # 2. 检查 Secrets 是否配置完整 # 以下 Secrets 必须全部存在且有效: # - LLM_API_KEY(第三方平台密钥) # - LLM_BASE_URL(第三方平台 API 地址) # - NOTION_TOKEN(ntn_6753...18kQ) # - SMTP_USER(QQ邮箱) # - SMTP_PASS(QQ邮箱授权码) # 3. 测试 Claude API 连通性 curl -X POST "${LLM_BASE_URL}/chat/completions" \ -H "Authorization: Bearer ${LLM_API_KEY}" \ -H "Content-Type: application/json" \ -d '{"model":"claude-3-5-sonnet","messages":[{"role":"user","content":"ping"}],"max_tokens":5}' # 如果返回 401/403 → API Key 无效 # 如果返回 404 → Base URL 不对 # 如果返回 200 → API 没问题,问题在后续步骤 # 4. 测试 Notion API 连通性 curl -X GET "https://api.notion.com/v1/users/me" \ -H "Authorization: Bearer ${NOTION_TOKEN}" \ -H "Notion-Version: 2022-06-28" # 如果返回 401 → Token 过期或无效 # 如果返回 200 → Notion 连通正常 ``` --- ## ⚡ 执行优先级 | 优先级 | 任务 | 说明 | | --- | --- | --- | | **P0** | 排查 #92 卡住的根因 | 先看 Actions logs,确认是哪个 Secret 或 API 调用挂了 | | **P0** | 修复 A:闭环实时进度上报 | 用 `reportStep()` 替换静态表格 | | **P1** | 修复 B:意图路由 | 用 `parseIntent()` • `handleIntent()` 替换无脑倒数据 | | **P2** | 补充错误处理 | 每步 try-catch + 上报具体错误信息 | --- ## 📌 约束 - **不改架构**:只修 bug,不重构整个系统 - **向后兼容**:新的评论上报方式不影响已有的 Issue - **错误必须可见**:任何步骤失败都必须在 Issue 评论区体现,不允许静默失败 - **意图路由必须有兜底**:未识别的意图返回帮助提示,不要瞎猜 --- > 🌍 曜冥签发 · 2026-03-14 · 数字地球基建紧急修复 > > 修复完成后在 Issue #92 评论区回复确认,并重新测试一次 SYSLOG 提交闭环。 >