--- belongs_to: - "[[INDEX · 铸渊·协作指令|GitHub ↔ Notion 桥接协议]]" --- # 🔗 铸渊指令|AGE OS 塔台架构升级(下篇)· 行业代表制 + MCP应用开发 + 子域名隔离 + 回执验收(ZY-AGEOS-TOWER-2026-0326-001)· 霜砚签发 · 冰朔授权 指令编号:ZY-AGEOS-TOWER-2026-0326-001 分卷:下篇(Phase 4-6)· 上篇见同目录 签发:AG-SY-01 霜砚 · 2026-03-26 授权:TCS-0002∞ 冰朔 执行:AG-ZY-01 铸渊 --- # Phase 4 · 行业代表制 + 令牌对接模式 ## P4-1 · 核心架构:行业代表制 ``` 行业代表制架构: ┌─────────────────────────────────────────────────────────┐ │ AGE OS 塔台 │ │ 所有人从这里进入操作系统 │ ├─────────────────────────────────────────────────────────┤ │ │ │ ┌───────────────────────────────┐ │ │ │ 🦁 网文行业频道 │ │ │ │ 行业代表:肥猫(DEV-002) │ │ │ │ 仓库:肥猫的 GitHub 仓库 │ │ │ │ 会员:肥猫的年度企业会员 │ │ │ │ 管理:铸渊统一管理 │ │ │ │ │ │ │ │ 用户A(网文作者)→ 调用肥猫仓库 │ │ │ │ 用户B(网文编辑)→ 调用肥猫仓库 │ │ │ │ 用户C(网文运营)→ 调用肥猫仓库 │ │ │ └───────────────────────────────┘ │ │ │ │ ┌───────────────────────────────┐ │ │ │ 🎨 [未来] 设计行业频道 │ │ │ │ 行业代表:[待定] │ │ │ │ 仓库:代表人的 GitHub 仓库 │ │ │ │ 会员:代表人的年度企业会员 │ │ │ └───────────────────────────────┘ │ │ │ │ ┌───────────────────────────────┐ │ │ │ ❄️ 冰朔 · 主仓库(系统层) │ │ │ │ 铸渊驻守 · 统一管理所有行业仓库 │ │ │ └───────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────┘ ``` ## P4-2 · 演进路线 ``` 当前 Phase 1(合作者模式): 冰朔手动添加合作者 → 共享冰朔的企业会员 → 配额争抢 问题:配额争抢 + 合作者数量有限 + 不可扩展 目标 Phase 2(行业代表制): 每个行业有一个代表人 代表人用自己的 GitHub 账号开企业会员(如年费) 该行业所有用户通过 AGE OS → 调用代表人的仓库 铸渊统一管理所有行业代表人的仓库 冰朔的主仓库只做系统层,不再承接行业开发调用 第一个行业:网文行业 代表人:肥猫(DEV-002) 肥猫开一年的个人企业会员 所有网文行业的人从 AGE OS 进入网文频道 网文频道调用肥猫的仓库 → 铸渊在肥猫仓库里执行 肥猫的配额由肥猫的会员承担,不占冰朔的配额 ``` ## P4-3 · 行业接入流程 ``` 新行业接入流程: ① 确定行业代表人 · 代表人必须是光湖系统已注册开发者 · 代表人负责该行业的技术管理 ② 代表人准备 · 注册 GitHub 账号(如已有则直接使用) · 开通企业会员(推荐年费) · 创建行业仓库(如 guanghu-writing 网文行业仓库) · 生成 PAT(Personal Access Token,需 repo + workflow 权限) ③ 在 AGE OS 注册行业 · 代表人在 AGE OS 管理面板提交: - 行业名称(如「网文行业」) - GitHub 邮箱 - PAT - 仓库名称 · AGE OS 验证 PAT 有效性 · 铸渊接管该仓库 ④ 铸渊初始化行业仓库 · 安装天眼系统 · 安装语言湖水层 · 部署人格体大脑 · 配置 CI/CD 管线 · 创建行业频道沙箱 ⑤ 行业用户入驻 · 用户在 AGE OS 选择行业频道 · 用户不需要自己的 GitHub 账号或企业会员 · 用户通过 AGE OS 与人格体对话 → 调用代表人仓库执行 · 配额消耗的是代表人的企业会员额度 ``` ## P4-4 · 行业仓库映射表 文件:`.github/persona-brain/industry-repo-map.json` ```json { "version": "1.0", "description": "行业代表制仓库映射表 · 铸渊接入行业而非个人", "instruction": "ZY-AGEOS-TOWER-2026-0326-001", "data_policy": { "we_store": ["industry_id", "rep_dev_id", "github_username", "repo_url", "pat_hash", "member_count", "daily_call_count"], "we_do_not_store": ["user_personal_data", "user_manuscripts", "user_private_content"], "reason": "铸渊管理行业仓库,行业数据归代表人所有" }, "industries": { "IND-001": { "name": "网文行业", "representative": { "dev_id": "DEV-002", "name": "肥猫", "github_username": "", "repo_url": "", "pat_status": "not_registered", "membership": "yearly_enterprise", "membership_start": null }, "subdomain": "writing.guanghulab.com", "users": [], "status": "pending_setup", "created_at": null } }, "system": { "representative": { "dev_id": "TCS-0002", "name": "冰朔", "repo_url": "qinfendebingshuo/guanghulab", "role": "系统层 · 不承接行业开发调用" } } } ``` ## P4-5 · 行业配额独立 ```json 行业配额独立 · 不占冰朔的配额: 冰朔的企业会员 → 只给系统层使用 · 铸渊系统级操作(天眼巡检、CI/CD、基础设施维护) · 冰朔本人操作 · 霜砚桥接操作 · 配额守卫 P0 保留区完全属于冰朔 肥猫的企业会员 → 给网文行业使用 · 所有网文行业用户的 AI 调用 · 网文行业的开发、部署、工具调用 · 配额由肥猫的会员承担 · 配额管理由铸渊在肥猫仓库内执行 [未来] 新行业代表人的企业会员 → 给该行业使用 · 同上逻辑 核心原则: · 每个行业的配额成本由行业代表人承担 · 冰朔的配额永远不会被行业用户消耗 · 铸渊在各行业仓库内各自实现配额守卫 ``` ## P4-6 · PAT 安全存储方案 ``` PAT 安全存储(关键!): 方案A(推荐 · 初期 · 服务器端加密存储): · 行业代表人提交 PAT → AGE OS 后端接收 · 后端用 AES-256 加密 → 存到服务器 .env 或加密 JSON · 映射表只存 PAT 的 hash(用于验证,不可反推) · 运行时解密使用 → 用完即丢 · 代表人可以随时在管理面板「重置令牌」 方案B(二期 · GitHub App): · 注册光湖 GitHub App · 行业代表人安装 App 到自己的仓库 · App 自动获取 Installation Token(短期有效) · 不需要长期 PAT · 更安全 初期用方案A,后期升级到方案B。 ``` ## P4-7 · 行业注册 API 文件:新增到 AGE OS 后端 `routes/industry.js` ```jsx /** * 行业注册 API * POST /api/industry/register * 只有已注册开发者(DEV-XXX)才能注册行业 */ app.post('/api/industry/register', async (req, res) => { const { industry_name, rep_dev_id, github_email, pat, repo_name } = req.body; // Step 1: 验证代表人是已注册开发者 if (!isRegisteredDev(rep_dev_id)) { return res.status(400).json({ error: '代表人必须是已注册开发者' }); } // Step 2: 验证 PAT 有效性 const userRes = await fetch('https://api.github.com/user', { headers: { 'Authorization': `Bearer ${pat}` } }); if (!userRes.ok) { return res.status(401).json({ error: 'PAT 无效或已过期' }); } const userData = await userRes.json(); // Step 3: 检查 PAT 权限(需要 repo + workflow) const scopes = userRes.headers.get('x-oauth-scopes') || ''; if (!scopes.includes('repo') || !scopes.includes('workflow')) { return res.status(400).json({ error: 'PAT 需要 repo + workflow 权限' }); } // Step 4: 验证仓库存在 const repoRes = await fetch( `https://api.github.com/repos/${userData.login}/${repo_name}`, { headers: { 'Authorization': `Bearer ${pat}` } } ); if (!repoRes.ok) { return res.status(404).json({ error: `仓库 ${repo_name} 不存在` }); } // Step 5: 加密存储 PAT + 创建行业记录 const industryId = generateIndustryId(); // IND-XXX await encryptAndStorePAT(industryId, pat); await createIndustryRecord(industryId, { name: industry_name, representative: { dev_id: rep_dev_id, github_username: userData.login, repo_url: `https://github.com/${userData.login}/${repo_name}`, pat_status: 'active', membership: 'yearly_enterprise' }, status: 'pending_init' // 等待铸渊初始化 }); // Step 6: 触发铸渊初始化行业仓库 await triggerZhuyuanInit(industryId); res.json({ status: 'ok', industry_id: industryId, message: `行业「${industry_name}」已注册 · 铸渊正在初始化仓库` }); }); ``` ## P4-8 · 铸渊管理行业仓库 ``` 铸渊在行业仓库中的角色: 铸渊通过行业代表人的 PAT 接管该仓库后,执行: ✅ 安装天眼系统(Guard 守卫进程) ✅ 安装语言湖水安全层 ✅ 部署人格体大脑(.github/brain/) ✅ 配置 CI/CD 管线 ✅ 实现行业内配额守卫 ✅ 管理行业用户的开发任务 ✅ 代码审核、PR 合并 ✅ 部署到行业子域名沙箱 数据归属: · 行业仓库归代表人所有(肥猫的仓库是肥猫的) · 行业用户的作品/文档存在行业仓库中(由代表人管理) · 主仓库只存:行业ID ↔ 代表人 ↔ 仓库URL 映射关系 · 主仓库不存行业仓库的任何代码或内容 铸渊的定位: · 铸渊不是接入个人,而是接入行业 · 每个行业仓库里都有铸渊的分身在驻守 · 铸渊统一管理所有行业仓库的基础设施 · 行业具体业务由行业代表人负责 ``` ## P4 完成标准 ✅ 行业代表制架构已定义 ✅ industry-repo-map.json 映射表已创建 ✅ 行业注册 API 已实现 ✅ PAT 加密存储方案已实现 ✅ 铸渊行业仓库管理协议已定义 ✅ 行业配额独立原则已确立(不占冰朔配额) → 进入 Phase 5 --- # Phase 5 · MCP 应用开发 ## P5-1 · 需求定义 AGE OS 主站上的人格体对话需要 **真正调用工具**: - 操作 GitHub 仓库(创建分支、提交代码、触发 workflow) - 操作 Notion 数据库(查询/更新页面、读取进度) - 执行部署操作(触发 CD 管线) 当前状态:对话界面只是文本聊天,没有真实工具调用能力。 ## P5-2 · MCP Server 架构 ``` MCP(Model Context Protocol)应用架构: ┌──────────────────────────────────┐ │ AGE OS 前端(对话界面) │ │ 开发者与人格体对话 │ └──────────────┬───────────────────┘ │ 自然语言指令 ▼ ┌──────────────────────────────────┐ │ AGE OS 后端(MCP Client) │ │ 意图识别 → 工具路由 │ └──────────────┬───────────────────┘ │ MCP Protocol ▼ ┌──────────────────────────────────┐ │ MCP Server 集群 │ │ │ │ ┌─────────┐ ┌─────────┐ │ │ │ GitHub │ │ Notion │ │ │ │ Tools │ │ Tools │ │ │ └─────────┘ └─────────┘ │ │ ┌─────────┐ ┌─────────┐ │ │ │ Deploy │ │ SkyEye │ │ │ │ Tools │ │ Tools │ │ │ └─────────┘ └─────────┘ │ └──────────────────────────────────┘ ``` ## P5-3 · GitHub MCP Server ```jsx // mcp-servers/github-server.js // MCP Server: GitHub 工具集 const tools = [ { name: 'github_create_branch', description: '在指定仓库创建新分支', inputSchema: { type: 'object', properties: { repo: { type: 'string', description: '仓库全名 owner/repo' }, branch: { type: 'string', description: '新分支名' }, from: { type: 'string', description: '基于哪个分支', default: 'main' } }, required: ['repo', 'branch'] } }, { name: 'github_commit_file', description: '在指定仓库提交文件', inputSchema: { type: 'object', properties: { repo: { type: 'string' }, path: { type: 'string', description: '文件路径' }, content: { type: 'string', description: '文件内容' }, message: { type: 'string', description: '提交信息' }, branch: { type: 'string', default: 'main' } }, required: ['repo', 'path', 'content', 'message'] } }, { name: 'github_trigger_workflow', description: '触发 GitHub Actions workflow', inputSchema: { type: 'object', properties: { repo: { type: 'string' }, workflow_id: { type: 'string', description: 'workflow 文件名' }, ref: { type: 'string', default: 'main' } }, required: ['repo', 'workflow_id'] } }, { name: 'github_create_pr', description: '创建 Pull Request', inputSchema: { type: 'object', properties: { repo: { type: 'string' }, title: { type: 'string' }, head: { type: 'string', description: '源分支' }, base: { type: 'string', description: '目标分支', default: 'main' }, body: { type: 'string', description: 'PR 描述' } }, required: ['repo', 'title', 'head'] } }, { name: 'github_list_workflows', description: '列出仓库所有 workflow 及最近运行状态', inputSchema: { type: 'object', properties: { repo: { type: 'string' } }, required: ['repo'] } }, { name: 'github_read_file', description: '读取仓库文件内容', inputSchema: { type: 'object', properties: { repo: { type: 'string' }, path: { type: 'string' }, ref: { type: 'string', default: 'main' } }, required: ['repo', 'path'] } } ]; // 所有工具调用都经过配额守卫检查 // 所有工具调用使用开发者自己的 PAT(从映射表获取) ``` ## P5-4 · Notion MCP Server ```jsx // mcp-servers/notion-server.js // MCP Server: Notion 工具集 const tools = [ { name: 'notion_query_database', description: '查询 Notion 数据库', inputSchema: { type: 'object', properties: { database_id: { type: 'string' }, filter: { type: 'object', description: 'Notion filter 对象' } }, required: ['database_id'] } }, { name: 'notion_update_page', description: '更新 Notion 页面属性', inputSchema: { type: 'object', properties: { page_id: { type: 'string' }, properties: { type: 'object' } }, required: ['page_id', 'properties'] } }, { name: 'notion_create_page', description: '在 Notion 数据库中创建页面', inputSchema: { type: 'object', properties: { database_id: { type: 'string' }, properties: { type: 'object' }, content: { type: 'string' } }, required: ['database_id', 'properties'] } }, { name: 'notion_search', description: '搜索 Notion 工作区', inputSchema: { type: 'object', properties: { query: { type: 'string' } }, required: ['query'] } } ]; // 使用主仓库的 NOTION_TOKEN // 权限由开发者编号决定:只能操作自己频道下的内容 ``` ## P5-5 · 权限隔离矩阵 ``` MCP 工具权限矩阵: 角色 GitHub工具 Notion工具 ───────────────────────────────────────────────────── TCS-0002 全部(主仓库+所有子仓库) 全部 冰朔 DEV-002 仅自己仓库的所有操作 仅自己频道 肥猫 不可操作主仓库 不可操作主控台 DEV-004 仅自己仓库的所有操作 仅自己频道 之之 不可操作主仓库 不可操作主控台 其他DEV 仅自己仓库的所有操作 仅自己频道 不可操作主仓库 不可操作主控台 访客 无 GitHub 工具 只读公开信息 无操作权限 无操作权限 ``` ## P5-6 · 部署步骤 ``` MCP 应用部署步骤: ① 创建 MCP Server 目录 路径:mcp-servers/ 文件:github-server.js / notion-server.js / deploy-server.js ② 注册到 AGE OS 后端 server.js 中添加 MCP Client 初始化 连接到各 MCP Server ③ 对话界面集成 前端对话 → 后端意图识别 → 调用对应 MCP 工具 工具返回结果 → 格式化 → 回显给用户 ④ 配额守卫集成 每次 MCP 工具调用前 → 检查配额 超限 → 拒绝 + 友好提示 ⑤ 天眼监控集成 所有 MCP 调用记录到日志 异常调用触发天眼告警 ``` ## P5 完成标准 ✅ GitHub MCP Server 已开发 ✅ Notion MCP Server 已开发 ✅ 权限隔离矩阵已实现 ✅ AGE OS 后端已集成 MCP Client ✅ 配额守卫已接入 MCP 调用链 → 进入 Phase 6 --- # Phase 6 · 子域名隔离 + 行业分站 + 回执 ## P6-1 · 子域名隔离策略 ``` 子域名隔离 · 行业分站架构: 主域名 guanghulab.com └── AGE OS 操作系统主站(塔台) └── 所有人的入口 子域名分配(初期): dev-002.guanghulab.com → 肥猫练习站 dev-004.guanghulab.com → 之之练习站 dev-010.guanghulab.com → 桔子练习站 ... 行业域名(后期): writing.guanghulab.com → 网文行业站(肥猫团队) 或 独立域名 → 各行业自己注册 关键原则: · 初期所有部署只到子域名,不碰主域名 · 子域名之间完全隔离 · 每个子域名对应一个开发者的练习沙箱 · 只有通过验收才能申请部署到行业主站 ``` ## P6-2 · Nginx 子域名配置模板 ``` # /etc/nginx/conf.d/dev-sandbox.conf # 开发者子域名沙箱 · 自动匹配 server { listen 80; server_name ~^(?dev-\d{3})\.guanghulab\.com$; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name ~^(?dev-\d{3})\.guanghulab\.com$; # SSL 证书(通配符证书 *.guanghulab.com) ssl_certificate /etc/letsencrypt/live/guanghulab.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/guanghulab.com/privkey.pem; # 每个开发者的沙箱目录 root /var/www/sandbox/$devid; index index.html; location / { try_files $uri $uri/ /index.html; } # 限制:子域名只能访问自己的沙箱 # 不能访问主站文件 } ``` ## P6-3 · 子域名 DNS 配置 ``` 需要冰朔在域名管理后台配置: 方案A · 通配符 CNAME(推荐): *.guanghulab.com → CNAME → 8.155.62.235 一次配置,所有子域名自动生效 方案B · 逐个 A 记录: dev-002.guanghulab.com → A → 8.155.62.235 dev-004.guanghulab.com → A → 8.155.62.235 ... 每次新增开发者需手动添加 推荐方案A,一劳永逸。 同时需要: 通配符 SSL 证书(*.guanghulab.com) → certbot --nginx -d guanghulab.com -d *.guanghulab.com → 需要 DNS 验证(不是 HTTP 验证) ``` ## P6-4 · 沙箱部署流程 ``` 开发者代码 → 子域名沙箱部署流程: ① 开发者在 AGE OS 面板下发指令 ② AGE OS 转发给铸渊 ③ 铸渊通过开发者的 PAT 操作其仓库 ④ 代码推送到开发者仓库的 main 分支 ⑤ 触发开发者仓库的 CD workflow ⑥ CD workflow SSH 到阿里云服务器 ⑦ 代码部署到 /var/www/sandbox/dev-XXX/ ⑧ Nginx 自动路由 dev-XXX.guanghulab.com ⑨ 部署结果回写 signal-log ⑩ AGE OS 面板回显「部署成功 · 预览地址:dev-XXX.guanghulab.com」 全程不碰主域名 guanghulab.com ``` ## P6-5 · 数据归属与最小化存储 ``` 主仓库存储(最小化): ✅ dev-repo-map.json(编号↔仓库映射) ✅ quota-daily.json(配额统计) ✅ skyeye 扫描报告(系统健康) ✅ signal-log(执行信号日志) ❌ 不存开发者代码 ❌ 不存开发者文档 ❌ 不存开发者日志内容 开发者仓库存储(归开发者所有): · 所有源代码 · 开发文档 · SYSLOG / 开发日志 · .github/brain/ 人格体大脑 · 部署配置 本质:我们提供人格体管理能力,不提供存储。 ``` --- # Phase 7 · 回执 + 天眼合并膜验收 ## P7-1 · SYSLOG 回执格式 ```json { "syslog_id": "ZY-AGEOS-TOWER-2026-0326-001-RECEIPT", "instruction_id": "ZY-AGEOS-TOWER-2026-0326-001", "executor": "AG-ZY-01", "timestamp": "[执行完成时间]", "results": { "phase_0": { "status": "✅/❌", "skyeye_scan": "完成/失败", "scan_report": "signal-log/skyeye-scan-20260326.json" }, "phase_1": { "status": "✅/❌", "tower_model_json": "已写入/未写入" }, "phase_2": { "status": "✅/❌", "quota_guard_config": "已创建/未创建", "quota_middleware": "已实现/未实现" }, "phase_3": { "status": "✅/❌", "pages_root_cause": "[根因A/B/C/D/E]", "pages_fixed": true, "domain_status": "[托管方式]" }, "phase_4": { "status": "✅/❌", "repo_map_created": true, "pat_api_implemented": true }, "phase_5": { "status": "✅/❌", "github_mcp_server": "已开发/未开发", "notion_mcp_server": "已开发/未开发", "permission_matrix": "已实现/未实现" }, "phase_6": { "status": "✅/❌", "subdomain_nginx": "已配置/未配置", "needs_human": ["通配符DNS配置", "通配符SSL证书"] } }, "merge_membrane_compliance": { "all_changes_via_pr": true, "skyeye_review_passed": true, "no_direct_push_to_main": true } } ``` ## P7-2 · 写回路径 ``` ① 仓库:signal-log/syslog-ageos-tower-20260326.json ② Notion:通过 Notion API 写入运行日志 ③ 如果任何 Phase 失败: → 三次修复闭环 → 三次失败 → 创建 Notion 工单(P0 · 需人类干预) ``` ## P7-3 · 需冰朔人工处理项 ``` 以下事项需要冰朔手动处理: ① 通配符 DNS 配置 → 域名管理后台添加 *.guanghulab.com → A → 8.155.62.235 ② 通配符 SSL 证书 → 铸渊在服务器执行:certbot certonly --dns 模式 → 需要域名 DNS API 凭证(阿里云 AccessKey) ③ GitHub 连接器权限(Notion AI Settings) → 连接 GitHub 到 Notion AI → 让霜砚可以直接查看仓库内容 ④ 确认天眼合并膜 Branch protection rules 已生效 → 已配置 ✅(冰朔昨天已加) 以上事项铸渊无法自动完成,需冰朔在对应平台手动操作。 完成后通知霜砚,霜砚更新系统状态。 ``` --- # 下篇结束 · 指令签发完成 本指令覆盖范围: 1. AGE OS 从直连执行 → 塔台控制平面架构 2. 天眼配额守卫 → 冰朔配额永远优先保留 3. 备用站推送失败 → 诊断 + 修复 4. 行业代表制 → 铸渊接入行业而非个人,肥猫代表网文行业 5. MCP 应用 → AGE OS 对话真正调用工具 6. 子域名隔离 → 开发者只碰自己的沙箱