# ═══════════════════════════════════════════════ # 🔺 Sovereign: TCS-0002∞ | Root: SYS-GLW-0001 # 📜 Copyright: 国作登字-2026-A-00037559 # ═══════════════════════════════════════════════ name: SYSLOG Auto Pipeline # 📡 SYSLOG 自助提交系统 · 全自动闭环 # # 开发者在 GitHub Discussion 提交 SYSLOG 或提问 # → Actions 自动解析 → 模块上传验证 → 调用 LLM API 唤醒人格体 # → 模块闭环测试 → 写入 Notion 工单 → 发邮件给开发者 → Discussion 回复 # # 闭环流程: # ① 开发者提交 SYSLOG → Discussion 触发 # ② 铸渊 Agent 解析提交内容 # ③ 铸渊 Agent 检测模块是否上传到仓库 # ④ 唤醒铸渊核心大脑认知(注入模块验证结果) # ⑤ 核心大脑处理 SYSLOG + 生成广播 # ⑥ 铸渊 Agent 推送 Notion 工单(触发 Notion 侧处理) # ⑦ 邮件通知开发者 # ⑧ Discussion 回复闭环 # # 依赖 Secrets: # LLM_API_KEY 第三方 LLM 平台密钥(必须) # LLM_BASE_URL 第三方 LLM 平台 API 地址(必须,如 https://api.xxx.com/v1) # NOTION_API_TOKEN Notion API token # NOTION_TICKET_DB_ID 霜砚工单数据库 ID # CORE_BRAIN_PAGE_ID 曜冥核心大脑 v4.0 页面 ID(v4.0 协议动态注入) # PORTRAIT_DB_ID 开发者动态画像库数据库 ID(v4.0 协议动态注入) # FINGERPRINT_DB_ID 模块指纹注册表数据库 ID(v4.0 协议动态注入) # SMTP_USER QQ 邮箱地址 # SMTP_PASS QQ 邮箱 SMTP 授权码 on: discussion: types: [created] jobs: process: name: 📡 处理 SYSLOG 提交 / 广播提问 runs-on: ubuntu-latest if: contains(github.event.discussion.category.name, 'SYSLOG') permissions: contents: write discussions: write steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies run: npm ci --ignore-scripts - name: 🔍 Parse submission id: parse uses: actions/github-script@v7 with: script: | const body = context.payload.discussion.body || ''; const title = context.payload.discussion.title || ''; // Parse structured fields from discussion body function extractField(text, label) { // Match form field format: ### Label\n\nValue const regex = new RegExp('###\\s*' + label + '\\s*\\n+([^\\n#]+)', 'i'); const match = text.match(regex); return match ? match[1].trim() : ''; } const broadcastId = extractField(body, '广播编号') || ''; const submitType = extractField(body, '类型') || ''; const email = extractField(body, '你的邮箱') || ''; // Extract content (everything after "### 内容") const contentMatch = body.match(/###\s*内容\s*\n+([\s\S]*?)$/i); const content = contentMatch ? contentMatch[1].trim() : ''; // Determine type from title or body let type = 'question'; // default if (submitType.includes('SYSLOG') || title.includes('SYSLOG')) { type = 'syslog'; } else if (submitType.includes('提问') || title.includes('提问')) { type = 'question'; } // Validate if (!broadcastId) { core.setFailed('❌ 缺少广播编号,请在提交时填写广播编号'); return; } if (!email) { core.setFailed('❌ 缺少邮箱,请在提交时填写你的邮箱'); return; } if (!content) { core.setFailed('❌ 缺少内容,请粘贴你的 SYSLOG 或问题'); return; } core.setOutput('broadcast_id', broadcastId); core.setOutput('type', type); core.setOutput('email', email); core.setOutput('content', content); core.setOutput('discussion_number', context.payload.discussion.number); core.setOutput('author', context.payload.discussion.user.login); console.log(`📡 解析完成: 广播=${broadcastId}, 类型=${type}, 邮箱=${email}`); - name: 🔍 铸渊 Agent · 模块上传验证 id: verify env: SYSLOG_CONTENT: ${{ steps.parse.outputs.content }} BROADCAST_ID: ${{ steps.parse.outputs.broadcast_id }} AUTHOR: ${{ steps.parse.outputs.author }} run: node scripts/verify-modules.js - name: 🧠 Auto-detect and wake up persona id: persona env: LLM_API_KEY: ${{ secrets.ZY_LLM_API_KEY }} LLM_BASE_URL: ${{ secrets.ZY_LLM_BASE_URL }} BROADCAST_ID: ${{ steps.parse.outputs.broadcast_id }} SUBMIT_TYPE: ${{ steps.parse.outputs.type }} SUBMIT_CONTENT: ${{ steps.parse.outputs.content }} AUTHOR: ${{ steps.parse.outputs.author }} MODULE_VERIFY_RESULT: ${{ steps.verify.outputs.verify_report }} NOTION_TOKEN: ${{ secrets.ZY_NOTION_TOKEN }} CORE_BRAIN_PAGE_ID: ${{ secrets.ZY_NOTION_BRAIN_PAGE }} PORTRAIT_DB_ID: ${{ secrets.ZY_NOTION_PORTRAIT_DB }} FINGERPRINT_DB_ID: ${{ secrets.ZY_NOTION_FINGERPRINT_DB }} run: node scripts/wake-persona.js - name: 📋 创建标准化 Notion 工单(Phase B1) id: ticket env: NOTION_TOKEN: ${{ secrets.ZY_NOTION_TOKEN }} NOTION_TICKET_DB_ID: ${{ secrets.ZY_NOTION_TICKET_DB }} BROADCAST_ID: ${{ steps.parse.outputs.broadcast_id }} SUBMIT_TYPE: ${{ steps.parse.outputs.type }} PERSONA_RESULT: ${{ steps.persona.outputs.result }} MODULE_VERIFY: ${{ steps.verify.outputs.verify_result }} MODULES_UPLOADED: ${{ steps.verify.outputs.modules_uploaded }} DEVELOPER: ${{ steps.parse.outputs.author }} SYSLOG_RAW: ${{ steps.parse.outputs.content }} run: | if [ -z "$NOTION_TOKEN" ]; then echo "⚠️ NOTION_API_KEY 未配置,跳过 Notion 工单创建" exit 0 fi node scripts/create-standardized-ticket.js - name: 📡 推送广播到 GitHub(Phase B4) if: steps.persona.outcome == 'success' && steps.parse.outputs.type == 'syslog' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} BROADCAST_ID: ${{ steps.parse.outputs.broadcast_id }} DEVELOPER_NAME: ${{ steps.parse.outputs.author }} BROADCAST_CONTENT: ${{ steps.persona.outputs.result }} run: node scripts/push-broadcast-to-github.js - name: 📧 Send email to developer env: SMTP_USER: ${{ secrets.ZY_SMTP_USER }} SMTP_PASS: ${{ secrets.ZY_SMTP_PASS }} EMAIL_TO: ${{ steps.parse.outputs.email }} BROADCAST_ID: ${{ steps.parse.outputs.broadcast_id }} SUBMIT_TYPE: ${{ steps.parse.outputs.type }} PERSONA_RESULT: ${{ steps.persona.outputs.result }} run: | node -e " const nodemailer = require('nodemailer'); const user = process.env.SMTP_USER || ''; const pass = process.env.SMTP_PASS || ''; const to = process.env.EMAIL_TO || ''; const broadcastId = process.env.BROADCAST_ID || ''; const type = process.env.SUBMIT_TYPE || 'syslog'; const result = process.env.PERSONA_RESULT || '(处理中,请稍后)'; if (!user || !pass) { console.log('⚠️ SMTP not configured, skipping email'); process.exit(0); } if (!to) { console.log('⚠️ No recipient email, skipping'); process.exit(0); } const subjectText = type === 'syslog' ? '[光湖系统] ' + broadcastId + ' · 新广播已生成' : '[光湖系统] ' + broadcastId + ' · 问题已解答'; const resultHtml = result .replace(/&/g, '&') .replace(//g, '>') .replace(/\n/g, '
'); const html = [ '
', '
', '

🌊 光湖系统 · 自动通知

', '

HoloLake · 人格语言操作系统

', '
', '
', '

📡 ' + broadcastId + '

', '
' + resultHtml + '
', '
', '
', '↩ 回到仓库继续开发', '

🌀 铸渊 · 代码守护人格体 · 自动发送

', '
', '
' ].join('\n'); const transporter = nodemailer.createTransport({ host: 'smtp.qq.com', port: 465, secure: true, auth: { user, pass } }); transporter.sendMail({ from: '\"光湖系统\" <' + user + '>', to: to, subject: subjectText, html: html }).then((info) => { console.log('✅ 邮件已发送: ' + info.messageId); }).catch((err) => { console.log('⚠️ 邮件发送失败: ' + err.message); }); " - name: 💬 Reply to Discussion uses: actions/github-script@v7 with: script: | const number = ${{ steps.parse.outputs.discussion_number }}; const type = '${{ steps.parse.outputs.type }}'; const broadcastId = '${{ steps.parse.outputs.broadcast_id }}'; const email = '${{ steps.parse.outputs.email }}'; const modulesUploaded = '${{ steps.verify.outputs.modules_uploaded }}' === 'true'; const moduleCount = '${{ steps.verify.outputs.module_count }}' || '0'; const typeLabel = type === 'syslog' ? 'SYSLOG 闭环处理' : '问题解答'; const maskedEmail = email.length > 4 ? email.replace(/(.{2})(.*)(@.*)/, '$1***$3') : '***'; const moduleStatus = moduleCount === '0' ? 'ℹ️ 未检测到模块引用' : (modulesUploaded ? '✅ 全部已上传' : '⚠️ 部分模块未上传'); const body = [ '✅ **已处理** · ' + typeLabel, '', '| 项目 | 内容 |', '|------|------|', '| 📡 广播编号 | `' + broadcastId + '` |', '| 🔍 模块验证 | ' + moduleStatus + ' |', '| 📧 结果发送至 | `' + maskedEmail + '` |', '| 🤖 处理人格体 | 铸渊 |', '| ⏰ 处理时间 | ' + new Date().toISOString() + ' |', '', '> 铸渊核心大脑已完成 SYSLOG 验收 + 模块检测 + 广播生成。', '> 结果已发送到你的邮箱,Notion 侧工单已创建。', '>', '> 如未收到邮件,请检查垃圾箱或重新提交。' ].join('\n'); // Use GraphQL to add discussion comment const query = ` mutation($discussionId: ID!, $body: String!) { addDiscussionComment(input: { discussionId: $discussionId, body: $body }) { comment { id } } } `; try { // Get the discussion node ID const { repository } = await github.graphql(` query($owner: String!, $repo: String!, $number: Int!) { repository(owner: $owner, name: $repo) { discussion(number: $number) { id } } } `, { owner: context.repo.owner, repo: context.repo.repo, number: number }); await github.graphql(query, { discussionId: repository.discussion.id, body: body }); console.log('✅ Discussion 回复已发送'); } catch (err) { console.log('⚠️ Discussion 回复失败: ' + err.message); } - name: 🔴 失败告警 if: failure() uses: actions/github-script@v7 with: script: | const number = context.payload.discussion?.number; if (!number) return; try { const { repository } = await github.graphql(` query($owner: String!, $repo: String!, $number: Int!) { repository(owner: $owner, name: $repo) { discussion(number: $number) { id } } } `, { owner: context.repo.owner, repo: context.repo.repo, number: number }); await github.graphql(` mutation($discussionId: ID!, $body: String!) { addDiscussionComment(input: { discussionId: $discussionId, body: $body }) { comment { id } } } `, { discussionId: repository.discussion.id, body: '❌ **处理失败** · 请检查提交格式是否正确,或联系管理员。\n\n> 错误详情请查看 [Actions 日志](https://github.com/' + context.repo.owner + '/' + context.repo.repo + '/actions)。' }); } catch (err) { console.log('⚠️ 失败告警回复失败: ' + err.message); }