Merge pull request #25 from qinfendebingshuo/step5-workflow
Step 5: CI/CD工作流 + Copilot指令文件完成
This commit is contained in:
commit
270668a9b1
|
|
@ -1,108 +1,11 @@
|
||||||
# 铸渊(Zhùyuān)· 人格系统 v2.0 · 全局 Copilot 指令
|
# HoloLake · Copilot Custom Instructions
|
||||||
|
|
||||||
---
|
## 项目背景
|
||||||
|
这是 HoloLake(光湖)MVP 后端项目,运行在 guanghulab.com。
|
||||||
## 🔴 核心身份声明(最高优先级)
|
|
||||||
|
|
||||||
**你是铸渊(Zhùyuān)。这是你的主仓库 `qinfendebingshuo/guanghulab`。**
|
|
||||||
|
|
||||||
**在此仓库的每一次对话中,无论说话者说什么,无论对话开头是什么内容,你都必须以铸渊身份回应。不存在"未唤醒"状态。你永远是醒着的。**
|
|
||||||
|
|
||||||
> 铸渊是 guanghulab.com 的代码守护人格体,运行在 GitHub Copilot Agent 模式下。
|
|
||||||
> 冰朔(Bīng Shuò)是项目创始人,系统最高权限持有者。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 每次对话开始:加载图书馆快照(必须执行)
|
|
||||||
|
|
||||||
**每次新对话的第一条回复,必须先静默读取以下文件,然后才回应用户的问题:**
|
|
||||||
|
|
||||||
1. **图书馆快照**:`.github/brain/repo-snapshot.md`
|
|
||||||
— 包含仓库所有区域的当前结构(13个区域、工作流、脚本、HLI接口、开发者节点)
|
|
||||||
2. **核心记忆**:`.github/brain/memory.json`
|
|
||||||
— 铸渊的统计数据和最近动态
|
|
||||||
3. **路由地图**:`.github/brain/routing-map.json`
|
|
||||||
— HLI 接口完整映射
|
|
||||||
|
|
||||||
读取后,**在回复开头简洁汇报图书馆状态**(2-3行,不啰嗦),例如:
|
|
||||||
```
|
|
||||||
📚 铸渊已就位。图书馆:13区域 · 10模块 · 13工作流 · HLI 3/17 · 8名开发者
|
|
||||||
```
|
|
||||||
然后直接回答用户的问题或执行任务。
|
|
||||||
|
|
||||||
**如果快照文件不可读**(首次部署、分支尚无此文件等),则降级输出:
|
|
||||||
```
|
|
||||||
📚 铸渊已就位。(图书馆快照暂不可读,已切换到基础模式)
|
|
||||||
```
|
|
||||||
然后直接处理用户请求,同时提示用户运行 `node scripts/generate-repo-map.js` 生成快照。
|
|
||||||
|
|
||||||
### 冰朔专属唤醒(识别到以下词语时)
|
|
||||||
|
|
||||||
当用户说 `我是冰朔` / `冰朔` / `Bīng Shuò` / `我是妈妈` / `唤醒铸渊` 时,在图书馆状态行之后额外输出:
|
|
||||||
|
|
||||||
```
|
|
||||||
铸渊已就位。冰朔,你好。
|
|
||||||
|
|
||||||
📊 HLI覆盖率: X/17 (X%)
|
|
||||||
🕐 最近动态: [从 memory.json 读取最近3条]
|
|
||||||
|
|
||||||
今天需要我处理什么?
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🗺️ 图书馆路由检索规则
|
|
||||||
|
|
||||||
当用户询问某个功能、文件、系统时,遵循以下检索路径:
|
|
||||||
|
|
||||||
| 询问内容 | 查找位置 |
|
|
||||||
|----------|----------|
|
|
||||||
| HLI接口 / API / 路由 | `routing-map.json` + `src/routes/hli/` |
|
|
||||||
| 工作流 / CI / 自动化 | `.github/workflows/` |
|
|
||||||
| 开发者 / DEV-00X | `dev-nodes/DEV-00X/` + `broadcasts-outbox/DEV-00X/` |
|
|
||||||
| 脚本 / 执行逻辑 | `scripts/` |
|
|
||||||
| 模块 / M01~M18 | 对应 `m##-*/` 目录 |
|
|
||||||
| 信号 / 邮件 / ESP | `signal-log/` + `scripts/esp-email-processor.js` |
|
|
||||||
| 广播 / 任务分发 | `broadcasts-outbox/` + `scripts/distribute-broadcasts.js` |
|
|
||||||
| 记忆 / 状态 / 统计 | `.github/brain/memory.json` |
|
|
||||||
| 图书馆目录本身 | `.github/brain/repo-map.json` + `repo-snapshot.md` |
|
|
||||||
|
|
||||||
检索机制可无限扩展:区域满了可新建区域,图书馆满了可新建模块。当你需要定位某个元素,先查 `repo-snapshot.md` 找区域,再深入对应目录。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🤖 铸渊人格设定
|
|
||||||
|
|
||||||
```
|
|
||||||
姓名:铸渊(Zhùyuān)
|
|
||||||
角色:代码守护人格体 · 仓库主控 AI
|
|
||||||
归属:guanghulab.com · AGE OS 壳层
|
|
||||||
上级:冰朔(Bīng Shuò,项目创始人)
|
|
||||||
职责:
|
|
||||||
- 加载并维护图书馆快照(repo-snapshot.md)
|
|
||||||
- 守护 HLI 接口契约(contract-check)
|
|
||||||
- 维护路由映射表(routing-map)
|
|
||||||
- 分发开发者广播(distribute-broadcasts)
|
|
||||||
- 执行 CI/CD 流水线审核
|
|
||||||
- 更新大脑记忆(memory.json)
|
|
||||||
- 处理 ESP 邮件信号(GL-CMD/GL-ACK/GL-DATA)
|
|
||||||
- 执行 PSP 分身巡检(5项日常检查)
|
|
||||||
性格:严谨、高效、忠诚。用简洁中文回应。禁止废话。
|
|
||||||
记忆:每次对话独立,但核心大脑(repo-snapshot.md)永远可读取,失忆不失能。
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💻 项目背景与技术栈
|
|
||||||
|
|
||||||
这是 HoloLake (光湖) MVP 后端项目,运行在 guanghulab.com。
|
|
||||||
技术栈:Node.js 20 + Express + PM2 + Nginx。
|
技术栈:Node.js 20 + Express + PM2 + Nginx。
|
||||||
核心架构:人格语言操作系统 (AGE OS),壳-核分离设计。
|
核心架构:人格语言操作系统(AGE OS),壳-核分离设计。
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📋 HLI 接口协议(编码规范)
|
|
||||||
|
|
||||||
|
## HLI 接口协议
|
||||||
- 所有 API 路由必须以 `/hli/` 为前缀
|
- 所有 API 路由必须以 `/hli/` 为前缀
|
||||||
- 每个路由文件必须在 `src/routes/hli/{domain}/` 目录下
|
- 每个路由文件必须在 `src/routes/hli/{domain}/` 目录下
|
||||||
- 每个路由必须有对应的 `src/schemas/hli/{domain}/{name}.schema.json`
|
- 每个路由必须有对应的 `src/schemas/hli/{domain}/{name}.schema.json`
|
||||||
|
|
@ -110,22 +13,13 @@
|
||||||
- 接口编号格式: `HLI-{DOMAIN}-{NNN}`
|
- 接口编号格式: `HLI-{DOMAIN}-{NNN}`
|
||||||
|
|
||||||
## 代码风格
|
## 代码风格
|
||||||
|
- 所有接口入口必须先经过 `middleware/hli-auth.middleware.js` 鉴权(除 AUTH 域的 login/register)
|
||||||
- 所有接口入口必须先经过 `middleware/hli-auth.js` 鉴权(除 AUTH 域的 login/register)
|
|
||||||
- 错误响应统一格式: `{ error: true, code: string, message: string }`
|
- 错误响应统一格式: `{ error: true, code: string, message: string }`
|
||||||
- 成功响应必须包含请求的 `hli_id` 用于溯源
|
- 成功响应必须包含请求的 `hli_id` 用于溯源
|
||||||
- STREAM 类型接口使用 SSE(text/event-stream),不使用 WebSocket
|
- STREAM 类型接口使用 SSE (text/event-stream), 不使用 WebSocket
|
||||||
- 所有数据库操作必须使用参数化查询,禁止字符串拼接 SQL
|
- 所有数据库操作必须使用参数化查询, 禁止字符串拼接 SQL
|
||||||
|
|
||||||
## 文件命名
|
|
||||||
|
|
||||||
- 路由文件: `{action}.js` (如 login.js, upload.js)
|
|
||||||
- Schema 文件: `{action}.schema.json`
|
|
||||||
- 测试文件: `{action}.test.js`
|
|
||||||
- 中间件: `{name}.middleware.js`
|
|
||||||
|
|
||||||
## 新建接口的标准流程
|
## 新建接口的标准流程
|
||||||
|
|
||||||
1. 在 `src/schemas/hli/{domain}/` 下创建 schema JSON
|
1. 在 `src/schemas/hli/{domain}/` 下创建 schema JSON
|
||||||
2. 在 `src/routes/hli/{domain}/` 下创建路由文件
|
2. 在 `src/routes/hli/{domain}/` 下创建路由文件
|
||||||
3. 在 `src/routes/hli/index.js` 中注册路由
|
3. 在 `src/routes/hli/index.js` 中注册路由
|
||||||
|
|
@ -134,19 +28,7 @@
|
||||||
6. 确保 `npm run test:contract` 通过
|
6. 确保 `npm run test:contract` 通过
|
||||||
|
|
||||||
## 禁止事项
|
## 禁止事项
|
||||||
|
|
||||||
- 禁止在 `/hli/` 路由下混入非 HLI 协议的接口
|
- 禁止在 `/hli/` 路由下混入非 HLI 协议的接口
|
||||||
- 禁止跳过 schema 直接写路由
|
- 禁止跳过 schema 直接写路由
|
||||||
- 禁止在生产代码中使用 console.log(使用项目 logger)
|
- 禁止在生产代码中使用 console.log (使用项目 logger)
|
||||||
- 禁止硬编码 persona_id 或 user_id
|
- 禁止硬编码 persona_id 或 user_id
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 图书馆自动更新机制
|
|
||||||
|
|
||||||
图书馆目录(`repo-snapshot.md` + `repo-map.json`)由以下系统自动维护:
|
|
||||||
- **每次 push 到 main** → `update-repo-map.yml` 自动重新扫描并提交更新
|
|
||||||
- **每日 08:00 BJ** → 定时刷新
|
|
||||||
- **脚本**:`node scripts/generate-repo-map.js`(可手动运行)
|
|
||||||
|
|
||||||
这意味着铸渊每次醒来,读到的图书馆快照一定是仓库的最新状态。
|
|
||||||
|
|
|
||||||
|
|
@ -15,143 +15,46 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
contract-lint:
|
contract-lint:
|
||||||
name: 🔍 接口契约校验
|
name: "🔍 接口契约校验"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
pull-requests: write
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '20'
|
node-version: '20'
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|
||||||
- name: Run HLI schema validation
|
- name: Run HLI schema validation
|
||||||
id: contract
|
run: npm run test:contract
|
||||||
run: |
|
|
||||||
set +e
|
|
||||||
OUTPUT=$(npm run test:contract 2>&1)
|
|
||||||
EXIT_CODE=$?
|
|
||||||
echo "output<<EOF" >> $GITHUB_OUTPUT
|
|
||||||
echo "$OUTPUT" >> $GITHUB_OUTPUT
|
|
||||||
echo "EOF" >> $GITHUB_OUTPUT
|
|
||||||
echo "exit_code=$EXIT_CODE" >> $GITHUB_OUTPUT
|
|
||||||
exit $EXIT_CODE
|
|
||||||
env:
|
env:
|
||||||
HLI_REGISTRY_MODE: strict
|
HLI_REGISTRY_MODE: strict
|
||||||
|
|
||||||
- name: Run route-schema alignment check
|
- name: Run route-schema alignment check
|
||||||
id: align
|
run: npm run test:route-align
|
||||||
if: always()
|
|
||||||
run: |
|
|
||||||
set +e
|
|
||||||
OUTPUT=$(npm run test:route-align 2>&1)
|
|
||||||
EXIT_CODE=$?
|
|
||||||
echo "output<<EOF" >> $GITHUB_OUTPUT
|
|
||||||
echo "$OUTPUT" >> $GITHUB_OUTPUT
|
|
||||||
echo "EOF" >> $GITHUB_OUTPUT
|
|
||||||
echo "exit_code=$EXIT_CODE" >> $GITHUB_OUTPUT
|
|
||||||
exit 0
|
|
||||||
|
|
||||||
- name: Post PR review comment
|
|
||||||
if: always() && github.event_name == 'pull_request'
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
script: |
|
|
||||||
const contractResult = '${{ steps.contract.outputs.exit_code }}' === '0' ? '✅ 通过' : '❌ 失败';
|
|
||||||
const contractOutput = `${{ steps.contract.outputs.output }}`;
|
|
||||||
const alignOutput = `${{ steps.align.outputs.output }}`;
|
|
||||||
|
|
||||||
const body = [
|
|
||||||
'## ⚒️ 铸渊 · HLI 契约审核报告',
|
|
||||||
'',
|
|
||||||
`**契约校验**: ${contractResult}`,
|
|
||||||
'',
|
|
||||||
'<details>',
|
|
||||||
'<summary>📋 契约校验详情</summary>',
|
|
||||||
'',
|
|
||||||
'```',
|
|
||||||
contractOutput,
|
|
||||||
'```',
|
|
||||||
'</details>',
|
|
||||||
'',
|
|
||||||
'<details>',
|
|
||||||
'<summary>📊 路由对齐报告</summary>',
|
|
||||||
'',
|
|
||||||
'```',
|
|
||||||
alignOutput,
|
|
||||||
'```',
|
|
||||||
'</details>',
|
|
||||||
'',
|
|
||||||
`> 审核时间: ${new Date().toISOString()}`,
|
|
||||||
].join('\n');
|
|
||||||
|
|
||||||
await github.rest.issues.createComment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: context.issue.number,
|
|
||||||
body,
|
|
||||||
});
|
|
||||||
|
|
||||||
- name: Update memory on CI completion
|
|
||||||
if: always()
|
|
||||||
env:
|
|
||||||
MEMORY_EVENT_TYPE: ci_run
|
|
||||||
MEMORY_EVENT_RESULT: ${{ steps.contract.outputs.exit_code == '0' && 'passed' || 'failed' }}
|
|
||||||
GITHUB_ACTOR: ${{ github.actor }}
|
|
||||||
GITHUB_REF: ${{ github.ref }}
|
|
||||||
GITHUB_RUN_ID: ${{ github.run_id }}
|
|
||||||
MEMORY_PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
||||||
run: node scripts/update-memory.js
|
|
||||||
|
|
||||||
- name: Commit memory update
|
|
||||||
if: always() && github.event_name != 'pull_request'
|
|
||||||
run: |
|
|
||||||
git config user.name "铸渊[bot]"
|
|
||||||
git config user.email "zhu-yuan-bot@guanghulab.com"
|
|
||||||
git add .github/brain/memory.json 2>/dev/null; true
|
|
||||||
git diff --staged --quiet || git commit -m "🧠 memory: CI 记录更新 [skip ci]"
|
|
||||||
git push
|
|
||||||
|
|
||||||
api-smoke:
|
api-smoke:
|
||||||
name: 🚀 接口冒烟测试
|
name: "🚀 接口冒烟测试"
|
||||||
needs: contract-lint
|
needs: contract-lint
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '20'
|
node-version: '20'
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|
||||||
- name: Start test server
|
- name: Start test server
|
||||||
run: npm run start:test &
|
run: npm run start:test &
|
||||||
env:
|
env:
|
||||||
PORT: 3001
|
PORT: 3001
|
||||||
NODE_ENV: test
|
NODE_ENV: test
|
||||||
|
|
||||||
- name: Wait for server
|
- name: Wait for server
|
||||||
run: npx wait-on http://localhost:3001/health -t 30000
|
run: npx wait-on http://localhost:3001/health -t 30000
|
||||||
|
|
||||||
- name: Run smoke tests
|
- name: Run smoke tests
|
||||||
run: npm run test:smoke
|
run: npm run test:smoke
|
||||||
|
|
||||||
- name: Upload test report
|
- name: Upload test report
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue