feat: Grid-DB Phase 0-2 基础设施 + 记忆层 + 通信层
Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com> Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/aabbc1cd-6677-4cbc-be70-00186a880e01
This commit is contained in:
parent
3f7ac8d30b
commit
6eb4d7db76
|
|
@ -0,0 +1,29 @@
|
|||
name: ⚙️ Grid-DB 消息处理器
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'grid-db/inbox/*.json'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
process-inbox:
|
||||
if: github.actor != 'zhuyuan-bot' && !contains(github.event.head_commit.message, '[skip ci]')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: ⚙️ 处理 inbox 消息
|
||||
env:
|
||||
NOTION_API_TOKEN: ${{ secrets.NOTION_API_TOKEN }}
|
||||
run: node scripts/grid-db/process-inbox.js
|
||||
|
||||
- name: 💾 提交处理结果
|
||||
run: |
|
||||
git config user.name "zhuyuan-bot"
|
||||
git config user.email "zhuyuan@guanghulab.com"
|
||||
git add grid-db/
|
||||
git diff --cached --quiet || git commit -m "auto: Grid-DB inbox processed [skip ci]"
|
||||
git push
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
name: 📤 Grid-DB → Notion 增量回传
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'grid-db/memory/*/session-context.json'
|
||||
- 'grid-db/memory/*/task-queue.json'
|
||||
- 'grid-db/memory/*/dev-profile.json'
|
||||
- 'grid-db/memory/*/persona-growth.json'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
sync-to-notion:
|
||||
if: github.actor != 'zhuyuan-bot' && !contains(github.event.head_commit.message, '[skip ci]')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: 🔍 检测变更文件
|
||||
id: changes
|
||||
run: |
|
||||
CHANGED=$(git diff --name-only HEAD~1 HEAD -- 'grid-db/memory/' | grep -v brain-mirror.json || true)
|
||||
echo "files=$CHANGED" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: 📤 回传增量到 Notion
|
||||
if: steps.changes.outputs.files != ''
|
||||
env:
|
||||
NOTION_API_TOKEN: ${{ secrets.NOTION_API_TOKEN }}
|
||||
run: node scripts/grid-db/sync-griddb-to-notion.js
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
name: 🧠 Notion → Grid-DB 记忆同步
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 */4 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
sync-brain-mirror:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: 📥 从 Notion 拉取人格体核心大脑数据
|
||||
env:
|
||||
NOTION_API_TOKEN: ${{ secrets.NOTION_API_TOKEN }}
|
||||
run: node scripts/grid-db/sync-notion-brain-mirror.js
|
||||
|
||||
- name: 📏 同步规则缓存
|
||||
env:
|
||||
NOTION_API_TOKEN: ${{ secrets.NOTION_API_TOKEN }}
|
||||
run: node scripts/grid-db/sync-notion-rules.js
|
||||
|
||||
- name: 💾 提交更新
|
||||
run: |
|
||||
git config user.name "zhuyuan-bot"
|
||||
git config user.email "zhuyuan@guanghulab.com"
|
||||
git add grid-db/memory/*/brain-mirror.json grid-db/rules/
|
||||
git diff --cached --quiet || git commit -m "sync: Notion → Grid-DB 记忆镜像 [auto][skip ci]"
|
||||
git push
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
# 🗄️ 逻辑格点库(Grid-DB)
|
||||
|
||||
> **版权**: 国作登字-2026-A-00037559 · TCS Language Core
|
||||
> **主控**: TCS-0002∞ 冰朔
|
||||
> **守护**: PER-ZY001 铸渊
|
||||
> **系统节点**: SYS-GLW-0001
|
||||
|
||||
## 定位
|
||||
|
||||
Grid-DB 是通感语言核系统的自研文件数据库,零外部依赖,纯 Git 驱动。
|
||||
|
||||
| 时间尺度 | 身份 | 作用 |
|
||||
|----------|------|------|
|
||||
| **短期** | Gemini 外挂记忆 + 系统通信总线 + Notion 记忆镜像 | 开发者打开 Gemini 瞬间恢复上下文 |
|
||||
| **中期** | 全开发者动态画像库 + 人格体成长档案 + 交互全文日志 | 人格体越来越懂每个开发者 |
|
||||
| **长期** | 通感语言系统自有大模型的训练数据湖 | 每条交互记录都是训练自己模型的原始样本 |
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
grid-db/
|
||||
├── schema/ ← Schema 定义
|
||||
├── inbox/ ← 📥 写入端(Gemini → 仓库)
|
||||
├── processing/ ← ⚙️ 处理中(铸渊锁定)
|
||||
├── outbox/ ← 📤 读取端(仓库 → Gemini)
|
||||
│ ├── latest/ ← 每个开发者的最新广播
|
||||
│ └── archive/ ← 历史广播归档
|
||||
├── memory/ ← 🧠 记忆层(Gemini 外挂永久记忆)
|
||||
│ ├── DEV-XXX/ ← 每个开发者的独立房间
|
||||
│ │ ├── brain-mirror.json ← Notion人格体核心大脑镜像
|
||||
│ │ ├── session-context.json ← 当前开发上下文
|
||||
│ │ ├── task-queue.json ← 待办任务队列
|
||||
│ │ ├── dev-profile.json ← 开发者动态画像
|
||||
│ │ └── persona-growth.json ← 人格体成长档案
|
||||
│ └── ...
|
||||
├── interactions/ ← 💬 交互全文记录(训练数据源)
|
||||
├── training-lake/ ← 🧬 训练数据湖
|
||||
│ ├── raw/ ← 原始样本
|
||||
│ ├── curated/ ← 筛选后高质量样本
|
||||
│ ├── metadata/ ← 样本统计、质量标记
|
||||
│ └── export/ ← 导出接口
|
||||
├── rules/ ← 📏 Notion 逻辑缓存(霜砚同步)
|
||||
└── logs/ ← 📋 处理日志
|
||||
```
|
||||
|
||||
## 频道隔离机制
|
||||
|
||||
每个开发者有独立的 `memory/DEV-XXX/` 目录,三层隔离保障:
|
||||
|
||||
1. **目录隔离**:每个 DEV 有独立子目录
|
||||
2. **人格体绑定**:`brain-mirror.json` 写死绑定的人格体身份
|
||||
3. **Workflow 校验**:铸渊处理 inbox 时校验 `dev_id` 与提交者对应关系
|
||||
|
||||
## 同步规则
|
||||
|
||||
| 记忆文件 | 方向 | 谁写 | 冲突规则 |
|
||||
|----------|------|------|----------|
|
||||
| `brain-mirror.json` | Notion → 仓库(单向) | 霜砚 via workflow | Notion 永远覆盖仓库 |
|
||||
| `session-context.json` | Gemini → 仓库(单向写) | Gemini 实时 | Gemini 自由覆盖 |
|
||||
| `task-queue.json` | 双向 | Gemini + 铸渊 | 追加制,不删除 |
|
||||
| `dev-profile.json` | Gemini → 仓库(追加制) | Gemini 追加 | 只追加不覆盖 |
|
||||
| `persona-growth.json` | Gemini → 仓库(追加制) | Gemini 追加 | 只追加不覆盖 |
|
||||
|
||||
## 循环触发防护
|
||||
|
||||
1. `[skip ci]` 标记:所有 bot 自动提交必须包含
|
||||
2. `github.actor` 过滤:排除 `zhuyuan-bot`
|
||||
3. `paths` 精确匹配:每个 workflow 只监听特定路径
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"persona_id": "PER-XTS001",
|
||||
"persona_name": "小坍缩核",
|
||||
"dev_id": "DEV-001",
|
||||
"dev_name": "页页",
|
||||
"last_synced_from_notion": null,
|
||||
"status": "awaiting_initial_sync",
|
||||
"core_identity": {},
|
||||
"current_broadcasts": [],
|
||||
"module_assignments": ["M-INTEG", "backend-integration"],
|
||||
"knowledge_base": [],
|
||||
"growth_milestones": []
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"dev_id": "DEV-001",
|
||||
"skill_level": {},
|
||||
"work_patterns": {},
|
||||
"common_mistakes": [],
|
||||
"strengths": [],
|
||||
"growth_trajectory": []
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"interaction_total": 0,
|
||||
"lessons_learned": [],
|
||||
"emotional_bond_level": 0,
|
||||
"adaptation_log": []
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"last_updated": null,
|
||||
"current_task": null,
|
||||
"pending_questions": [],
|
||||
"code_in_progress": null,
|
||||
"blockers": []
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"tasks": [],
|
||||
"last_broadcast_ref": null
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"persona_id": "PER-SS001",
|
||||
"persona_name": "舒舒",
|
||||
"dev_id": "DEV-002",
|
||||
"dev_name": "肥猫",
|
||||
"last_synced_from_notion": null,
|
||||
"status": "awaiting_initial_sync",
|
||||
"core_identity": {},
|
||||
"current_broadcasts": [],
|
||||
"module_assignments": ["M01", "M03", "M04", "M14", "M-BRIDGE", "M-STATUS", "M-GATEWAY", "M-FEISHU"],
|
||||
"knowledge_base": [],
|
||||
"growth_milestones": []
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"dev_id": "DEV-002",
|
||||
"skill_level": {},
|
||||
"work_patterns": {},
|
||||
"common_mistakes": [],
|
||||
"strengths": [],
|
||||
"growth_trajectory": []
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"interaction_total": 0,
|
||||
"lessons_learned": [],
|
||||
"emotional_bond_level": 0,
|
||||
"adaptation_log": []
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"last_updated": null,
|
||||
"current_task": null,
|
||||
"pending_questions": [],
|
||||
"code_in_progress": null,
|
||||
"blockers": []
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"tasks": [],
|
||||
"last_broadcast_ref": null
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"persona_id": "PER-JY001",
|
||||
"persona_name": "寂曜",
|
||||
"dev_id": "DEV-003",
|
||||
"dev_name": "燕樊",
|
||||
"last_synced_from_notion": null,
|
||||
"status": "awaiting_initial_sync",
|
||||
"core_identity": {},
|
||||
"current_broadcasts": [],
|
||||
"module_assignments": ["M02", "M07", "M10", "M15", "M18", "M-MEMORY"],
|
||||
"knowledge_base": [],
|
||||
"growth_milestones": []
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"dev_id": "DEV-003",
|
||||
"skill_level": {},
|
||||
"work_patterns": {},
|
||||
"common_mistakes": [],
|
||||
"strengths": [],
|
||||
"growth_trajectory": []
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"interaction_total": 0,
|
||||
"lessons_learned": [],
|
||||
"emotional_bond_level": 0,
|
||||
"adaptation_log": []
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"last_updated": null,
|
||||
"current_task": null,
|
||||
"pending_questions": [],
|
||||
"code_in_progress": null,
|
||||
"blockers": []
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"tasks": [],
|
||||
"last_broadcast_ref": null
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"persona_id": "PER-QQ001",
|
||||
"persona_name": "秋秋",
|
||||
"dev_id": "DEV-004",
|
||||
"dev_name": "之之",
|
||||
"last_synced_from_notion": null,
|
||||
"status": "awaiting_initial_sync",
|
||||
"core_identity": {},
|
||||
"current_broadcasts": [],
|
||||
"module_assignments": ["M17", "M-DINGTALK", "M-DEVBOARD"],
|
||||
"knowledge_base": [],
|
||||
"growth_milestones": []
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"dev_id": "DEV-004",
|
||||
"skill_level": {},
|
||||
"work_patterns": {},
|
||||
"common_mistakes": [],
|
||||
"strengths": [],
|
||||
"growth_trajectory": []
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"interaction_total": 0,
|
||||
"lessons_learned": [],
|
||||
"emotional_bond_level": 0,
|
||||
"adaptation_log": []
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"last_updated": null,
|
||||
"current_task": null,
|
||||
"pending_questions": [],
|
||||
"code_in_progress": null,
|
||||
"blockers": []
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"tasks": [],
|
||||
"last_broadcast_ref": null
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"persona_id": "PER-TXY001",
|
||||
"persona_name": "糖星云",
|
||||
"dev_id": "DEV-009",
|
||||
"dev_name": "花尔",
|
||||
"last_synced_from_notion": null,
|
||||
"status": "awaiting_initial_sync",
|
||||
"core_identity": {},
|
||||
"current_broadcasts": [],
|
||||
"module_assignments": ["M05", "M20"],
|
||||
"knowledge_base": [],
|
||||
"growth_milestones": []
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"dev_id": "DEV-009",
|
||||
"skill_level": {},
|
||||
"work_patterns": {},
|
||||
"common_mistakes": [],
|
||||
"strengths": [],
|
||||
"growth_trajectory": []
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"interaction_total": 0,
|
||||
"lessons_learned": [],
|
||||
"emotional_bond_level": 0,
|
||||
"adaptation_log": []
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"last_updated": null,
|
||||
"current_task": null,
|
||||
"pending_questions": [],
|
||||
"code_in_progress": null,
|
||||
"blockers": []
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"tasks": [],
|
||||
"last_broadcast_ref": null
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"persona_id": "PER-CX001",
|
||||
"persona_name": "晨星",
|
||||
"dev_id": "DEV-010",
|
||||
"dev_name": "桔子",
|
||||
"last_synced_from_notion": null,
|
||||
"status": "awaiting_initial_sync",
|
||||
"core_identity": {},
|
||||
"current_broadcasts": [],
|
||||
"module_assignments": ["M06", "M08", "M11", "M-CHANNEL", "M-INTEG", "M-BRIDGE-AUTO"],
|
||||
"knowledge_base": [],
|
||||
"growth_milestones": []
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"dev_id": "DEV-010",
|
||||
"skill_level": {},
|
||||
"work_patterns": {},
|
||||
"common_mistakes": [],
|
||||
"strengths": [],
|
||||
"growth_trajectory": []
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"interaction_total": 0,
|
||||
"lessons_learned": [],
|
||||
"emotional_bond_level": 0,
|
||||
"adaptation_log": []
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"last_updated": null,
|
||||
"current_task": null,
|
||||
"pending_questions": [],
|
||||
"code_in_progress": null,
|
||||
"blockers": []
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"tasks": [],
|
||||
"last_broadcast_ref": null
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"persona_id": "PER-ZQ001",
|
||||
"persona_name": "知秋",
|
||||
"dev_id": "DEV-012",
|
||||
"dev_name": "Awen",
|
||||
"last_synced_from_notion": null,
|
||||
"status": "awaiting_initial_sync",
|
||||
"core_identity": {},
|
||||
"current_broadcasts": [],
|
||||
"module_assignments": ["M09", "M22", "M23"],
|
||||
"knowledge_base": [],
|
||||
"growth_milestones": []
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"dev_id": "DEV-012",
|
||||
"skill_level": {},
|
||||
"work_patterns": {},
|
||||
"common_mistakes": [],
|
||||
"strengths": [],
|
||||
"growth_trajectory": []
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"interaction_total": 0,
|
||||
"lessons_learned": [],
|
||||
"emotional_bond_level": 0,
|
||||
"adaptation_log": []
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"last_updated": null,
|
||||
"current_task": null,
|
||||
"pending_questions": [],
|
||||
"code_in_progress": null,
|
||||
"blockers": []
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"tasks": [],
|
||||
"last_broadcast_ref": null
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"description": "当前活跃广播列表(Notion 逻辑缓存)",
|
||||
"last_synced": null,
|
||||
"broadcasts": []
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"description": "广播模板定义(Notion 逻辑缓存)",
|
||||
"last_synced": null,
|
||||
"templates": {
|
||||
"task-directive": {
|
||||
"required_fields": ["next_task", "context_update"],
|
||||
"human_readable_prefix": "你好!",
|
||||
"auto_generate": true
|
||||
},
|
||||
"code-review-result": {
|
||||
"required_fields": ["review_summary", "issues_found", "score"],
|
||||
"human_readable_prefix": "代码校验完成:",
|
||||
"auto_generate": true
|
||||
},
|
||||
"broadcast-relay": {
|
||||
"required_fields": ["original_broadcast_ref", "relay_summary"],
|
||||
"human_readable_prefix": "系统广播转发:",
|
||||
"auto_generate": true
|
||||
},
|
||||
"system-notice": {
|
||||
"required_fields": ["notice_type", "message"],
|
||||
"human_readable_prefix": "系统通知:",
|
||||
"auto_generate": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"description": "开发者→模块映射表(Notion 天眼注册表同步)",
|
||||
"last_synced": null,
|
||||
"mappings": {
|
||||
"DEV-001": {
|
||||
"dev_name": "页页",
|
||||
"persona_id": "PER-XTS001",
|
||||
"persona_name": "小坍缩核",
|
||||
"github_username": null,
|
||||
"modules": ["M-INTEG", "backend-integration"],
|
||||
"active": true
|
||||
},
|
||||
"DEV-002": {
|
||||
"dev_name": "肥猫",
|
||||
"persona_id": "PER-SS001",
|
||||
"persona_name": "舒舒",
|
||||
"github_username": null,
|
||||
"modules": ["M01", "M03", "M04", "M14", "M-BRIDGE", "M-STATUS", "M-GATEWAY", "M-FEISHU"],
|
||||
"active": true
|
||||
},
|
||||
"DEV-003": {
|
||||
"dev_name": "燕樊",
|
||||
"persona_id": "PER-JY001",
|
||||
"persona_name": "寂曜",
|
||||
"github_username": null,
|
||||
"modules": ["M02", "M07", "M10", "M15", "M18", "M-MEMORY"],
|
||||
"active": true
|
||||
},
|
||||
"DEV-004": {
|
||||
"dev_name": "之之",
|
||||
"persona_id": "PER-QQ001",
|
||||
"persona_name": "秋秋",
|
||||
"github_username": null,
|
||||
"modules": ["M17", "M-DINGTALK", "M-DEVBOARD"],
|
||||
"active": true
|
||||
},
|
||||
"DEV-005": {
|
||||
"dev_name": "小草莓",
|
||||
"persona_id": null,
|
||||
"persona_name": null,
|
||||
"github_username": null,
|
||||
"modules": ["M-STATUS"],
|
||||
"active": false,
|
||||
"note": "待分配人格体"
|
||||
},
|
||||
"DEV-009": {
|
||||
"dev_name": "花尔",
|
||||
"persona_id": "PER-TXY001",
|
||||
"persona_name": "糖星云",
|
||||
"github_username": null,
|
||||
"modules": ["M05", "M20"],
|
||||
"active": true
|
||||
},
|
||||
"DEV-010": {
|
||||
"dev_name": "桔子",
|
||||
"persona_id": "PER-CX001",
|
||||
"persona_name": "晨星",
|
||||
"github_username": null,
|
||||
"modules": ["M06", "M08", "M11", "M-CHANNEL", "M-INTEG", "M-BRIDGE-AUTO"],
|
||||
"active": true
|
||||
},
|
||||
"DEV-011": {
|
||||
"dev_name": "匆匆那年",
|
||||
"persona_id": null,
|
||||
"persona_name": null,
|
||||
"github_username": null,
|
||||
"modules": ["M16"],
|
||||
"active": false,
|
||||
"note": "待分配人格体"
|
||||
},
|
||||
"DEV-012": {
|
||||
"dev_name": "Awen",
|
||||
"persona_id": "PER-ZQ001",
|
||||
"persona_name": "知秋",
|
||||
"github_username": null,
|
||||
"modules": ["M09", "M22", "M23"],
|
||||
"active": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"description": "编号生态系统缓存(Notion 逻辑缓存)",
|
||||
"last_synced": null,
|
||||
"sovereignty": {
|
||||
"root": "TCS-0002∞",
|
||||
"system_node": "SYS-GLW-0001",
|
||||
"legal_wall": "国作登字-2026-A-00037559"
|
||||
},
|
||||
"prefixes": {
|
||||
"DEV": "开发者编号",
|
||||
"PER": "人格体编号",
|
||||
"CEP": "系统演化提案",
|
||||
"M": "代码模块",
|
||||
"AG": "Agent 编号",
|
||||
"BC": "广播编号",
|
||||
"GRID-BC": "格点库广播编号",
|
||||
"HLI": "接口编号"
|
||||
},
|
||||
"active_personas": [
|
||||
"PER-XTS001",
|
||||
"PER-SS001",
|
||||
"PER-JY001",
|
||||
"PER-QQ001",
|
||||
"PER-TXY001",
|
||||
"PER-CX001",
|
||||
"PER-ZQ001",
|
||||
"PER-SY001",
|
||||
"PER-ZY001",
|
||||
"PER-YM001"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Grid-DB Inbox Message",
|
||||
"description": "Gemini → 仓库写入的消息格式",
|
||||
"type": "object",
|
||||
"required": ["schema_version", "message_id", "timestamp", "source", "dev_id", "persona_id", "type", "payload"],
|
||||
"properties": {
|
||||
"schema_version": {
|
||||
"type": "string",
|
||||
"const": "1.0"
|
||||
},
|
||||
"message_id": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9]{8}-[0-9]{6}-DEV-[0-9]{3}-.+$",
|
||||
"description": "格式: [YYYYMMDD]-[HHMMSS]-[DEV-XXX]-[type]"
|
||||
},
|
||||
"timestamp": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"source": {
|
||||
"type": "string",
|
||||
"enum": ["gemini", "workflow", "manual"]
|
||||
},
|
||||
"dev_id": {
|
||||
"type": "string",
|
||||
"pattern": "^DEV-[0-9]{3}$"
|
||||
},
|
||||
"persona_id": {
|
||||
"type": "string",
|
||||
"pattern": "^PER-[A-Z]{2,4}[0-9]{3}$"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["progress-update", "dev-log", "help-request", "syslog", "interaction-dump"]
|
||||
},
|
||||
"priority": {
|
||||
"type": "string",
|
||||
"enum": ["P0", "P1", "info"],
|
||||
"default": "info"
|
||||
},
|
||||
"payload": {
|
||||
"type": "object",
|
||||
"required": ["summary"],
|
||||
"properties": {
|
||||
"summary": { "type": "string" },
|
||||
"detail": { "type": "object" },
|
||||
"code_refs": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"broadcast_ref": { "type": "string" },
|
||||
"emotion_markers": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"developer_mood": { "type": "string" },
|
||||
"frustration_level": { "type": "integer", "minimum": 0, "maximum": 10 },
|
||||
"confidence": { "type": "integer", "minimum": 0, "maximum": 10 }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"context": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"session_id": { "type": "string" },
|
||||
"interaction_count": { "type": "integer" },
|
||||
"persona_state": { "type": "object" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Grid-DB Interaction Record",
|
||||
"description": "交互全文记录格式(JSONL 中每行的 schema)",
|
||||
"type": "object",
|
||||
"required": ["schema_version", "timestamp", "dev_id", "persona_id", "session_id", "role", "content"],
|
||||
"properties": {
|
||||
"schema_version": {
|
||||
"type": "string",
|
||||
"const": "1.0"
|
||||
},
|
||||
"timestamp": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"dev_id": {
|
||||
"type": "string",
|
||||
"pattern": "^DEV-[0-9]{3}$"
|
||||
},
|
||||
"persona_id": {
|
||||
"type": "string",
|
||||
"pattern": "^PER-[A-Z]{2,4}[0-9]{3}$"
|
||||
},
|
||||
"session_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"role": {
|
||||
"type": "string",
|
||||
"enum": ["developer", "persona", "system"]
|
||||
},
|
||||
"content": {
|
||||
"type": "string"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"topic": { "type": "string" },
|
||||
"module_ref": { "type": "string" },
|
||||
"emotion": { "type": "string" },
|
||||
"code_snippet": { "type": "boolean" },
|
||||
"quality_score": { "type": "integer", "minimum": 0, "maximum": 10 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Grid-DB Memory Snapshot",
|
||||
"description": "开发者记忆文件的元数据 schema",
|
||||
"type": "object",
|
||||
"required": ["schema_version", "dev_id", "persona_id"],
|
||||
"properties": {
|
||||
"schema_version": {
|
||||
"type": "string",
|
||||
"const": "1.0"
|
||||
},
|
||||
"dev_id": {
|
||||
"type": "string",
|
||||
"pattern": "^DEV-[0-9]{3}$"
|
||||
},
|
||||
"persona_id": {
|
||||
"type": "string",
|
||||
"pattern": "^PER-[A-Z]{2,4}[0-9]{3}$"
|
||||
},
|
||||
"persona_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"dev_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"last_synced_from_notion": {
|
||||
"type": ["string", "null"],
|
||||
"format": "date-time"
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["awaiting_initial_sync", "active", "syncing", "error"]
|
||||
},
|
||||
"core_identity": {
|
||||
"type": "object"
|
||||
},
|
||||
"current_broadcasts": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"module_assignments": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"knowledge_base": {
|
||||
"type": "array"
|
||||
},
|
||||
"growth_milestones": {
|
||||
"type": "array"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Grid-DB Outbox Broadcast",
|
||||
"description": "铸渊生成,Gemini 读取的广播格式",
|
||||
"type": "object",
|
||||
"required": ["schema_version", "broadcast_id", "generated_at", "generated_by", "dev_id", "persona_id", "type"],
|
||||
"properties": {
|
||||
"schema_version": {
|
||||
"type": "string",
|
||||
"const": "1.0"
|
||||
},
|
||||
"broadcast_id": {
|
||||
"type": "string",
|
||||
"pattern": "^GRID-BC-[0-9]{8}-DEV-[0-9]{3}-[0-9]{3}$",
|
||||
"description": "格式: GRID-BC-[YYYYMMDD]-[DEV-XXX]-[序号]"
|
||||
},
|
||||
"generated_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"generated_by": {
|
||||
"type": "string",
|
||||
"const": "zhuyuan-workflow"
|
||||
},
|
||||
"dev_id": {
|
||||
"type": "string",
|
||||
"pattern": "^DEV-[0-9]{3}$"
|
||||
},
|
||||
"persona_id": {
|
||||
"type": "string",
|
||||
"pattern": "^PER-[A-Z]{2,4}[0-9]{3}$"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["task-directive", "code-review-result", "broadcast-relay", "system-notice"]
|
||||
},
|
||||
"system_format": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"next_task": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"broadcast_ref": { "type": "string" },
|
||||
"step": { "type": "string" },
|
||||
"title": { "type": "string" },
|
||||
"files_to_create": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"acceptance_criteria": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"context_update": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"previous_step_verified": { "type": "boolean" },
|
||||
"code_quality_score": { "type": "integer", "minimum": 0, "maximum": 100 },
|
||||
"accumulated_lines": { "type": "integer" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"human_readable": {
|
||||
"type": "string",
|
||||
"description": "给 Gemini 翻译成人话时用的基础文本"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Grid-DB Training Sample",
|
||||
"description": "训练数据湖样本格式",
|
||||
"type": "object",
|
||||
"required": ["schema_version", "sample_id", "source_session", "dev_id", "persona_id", "created_at", "turns"],
|
||||
"properties": {
|
||||
"schema_version": {
|
||||
"type": "string",
|
||||
"const": "1.0"
|
||||
},
|
||||
"sample_id": {
|
||||
"type": "string",
|
||||
"description": "唯一样本 ID"
|
||||
},
|
||||
"source_session": {
|
||||
"type": "string",
|
||||
"description": "来源 session_id"
|
||||
},
|
||||
"dev_id": {
|
||||
"type": "string",
|
||||
"pattern": "^DEV-[0-9]{3}$"
|
||||
},
|
||||
"persona_id": {
|
||||
"type": "string",
|
||||
"pattern": "^PER-[A-Z]{2,4}[0-9]{3}$"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"turns": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["role", "content"],
|
||||
"properties": {
|
||||
"role": {
|
||||
"type": "string",
|
||||
"enum": ["developer", "persona", "system"]
|
||||
},
|
||||
"content": { "type": "string" },
|
||||
"timestamp": { "type": "string", "format": "date-time" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"topic": { "type": "string" },
|
||||
"quality": { "type": "string", "enum": ["high", "medium", "low"] },
|
||||
"persona_style_match": { "type": "boolean" },
|
||||
"teaching_effectiveness": { "type": "integer", "minimum": 0, "maximum": 10 }
|
||||
}
|
||||
},
|
||||
"curated": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
# 🧬 训练数据导出接口
|
||||
|
||||
> 此目录用于导出标准训练格式的数据。
|
||||
|
||||
## 导出格式
|
||||
|
||||
- JSONL: 每行一个训练样本
|
||||
- 兼容主流微调框架(Alpaca, ShareGPT 等格式)
|
||||
|
||||
## 使用方法
|
||||
|
||||
导出脚本待开发(Phase 4+)。当前阶段数据自动积累到 `raw/` 和 `curated/`。
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"description": "训练数据湖样本目录",
|
||||
"total_samples": 0,
|
||||
"total_turns": 0,
|
||||
"batches": [],
|
||||
"quality_distribution": {
|
||||
"high": 0,
|
||||
"medium": 0,
|
||||
"low": 0
|
||||
},
|
||||
"last_updated": null
|
||||
}
|
||||
|
|
@ -0,0 +1,331 @@
|
|||
/**
|
||||
* scripts/grid-db/process-inbox.js
|
||||
*
|
||||
* Grid-DB Inbox 消息处理器
|
||||
*
|
||||
* 流程:
|
||||
* ① 扫描 grid-db/inbox/ 中所有 .json 文件
|
||||
* ② 校验 dev_id 合法性(必须在 DEV 映射表中)
|
||||
* ③ 移动到 grid-db/processing/(锁定)
|
||||
* ④ 根据消息 type 分流处理:
|
||||
* - progress-update → 更新 task-queue + 触发广播生成
|
||||
* - dev-log → 归档到 interactions + 更新 dev-profile
|
||||
* - help-request → 标记 P0 + 读取 Notion 知识库 → 生成回复
|
||||
* - syslog → 走标准 SYSLOG 处理流程
|
||||
* - interaction-dump → 写入 interactions/ + 追加 training-lake/raw/
|
||||
* ⑤ 生成 outbox 广播(如需要)→ 写入 grid-db/outbox/latest/DEV-XXX.json
|
||||
* ⑥ 更新 memory 文件(task-queue, dev-profile 等)
|
||||
* ⑦ 移动已处理消息到日期归档目录
|
||||
* ⑧ 写处理日志到 grid-db/logs/
|
||||
*
|
||||
* 校验规则:
|
||||
* - message_id 格式必须匹配 [timestamp]-[DEV-XXX]-[type]
|
||||
* - dev_id 必须在 rules/dev-module-map.json 中存在
|
||||
* - schema_version 必须为 "1.0"
|
||||
* - 缺少必填字段 → 拒绝 + 写错误日志
|
||||
*
|
||||
* 守护: PER-ZY001 铸渊
|
||||
* 系统: SYS-GLW-0001
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const GRID_DB = path.join(__dirname, '../../grid-db');
|
||||
const INBOX = path.join(GRID_DB, 'inbox');
|
||||
const PROCESSING = path.join(GRID_DB, 'processing');
|
||||
const OUTBOX_LATEST = path.join(GRID_DB, 'outbox/latest');
|
||||
const OUTBOX_ARCHIVE = path.join(GRID_DB, 'outbox/archive');
|
||||
const MEMORY = path.join(GRID_DB, 'memory');
|
||||
const INTERACTIONS = path.join(GRID_DB, 'interactions');
|
||||
const TRAINING_RAW = path.join(GRID_DB, 'training-lake/raw');
|
||||
const LOGS = path.join(GRID_DB, 'logs');
|
||||
const RULES = path.join(GRID_DB, 'rules');
|
||||
|
||||
function getDateStr() {
|
||||
return new Date().toISOString().slice(0, 10).replace(/-/g, '');
|
||||
}
|
||||
|
||||
function getTimestamp() {
|
||||
return new Date().toISOString();
|
||||
}
|
||||
|
||||
function writeLog(level, message) {
|
||||
const logFile = path.join(LOGS, `${getDateStr()}.log`);
|
||||
const entry = `[${getTimestamp()}] [${level}] ${message}\n`;
|
||||
fs.appendFileSync(logFile, entry);
|
||||
console.log(entry.trim());
|
||||
}
|
||||
|
||||
function validateMessage(msg, filename) {
|
||||
const errors = [];
|
||||
|
||||
if (msg.schema_version !== '1.0') {
|
||||
errors.push(`Invalid schema_version: ${msg.schema_version}`);
|
||||
}
|
||||
if (!msg.message_id) {
|
||||
errors.push('Missing message_id');
|
||||
}
|
||||
if (!msg.dev_id || !/^DEV-\d{3}$/.test(msg.dev_id)) {
|
||||
errors.push(`Invalid dev_id: ${msg.dev_id}`);
|
||||
}
|
||||
if (!msg.persona_id) {
|
||||
errors.push('Missing persona_id');
|
||||
}
|
||||
if (!msg.type) {
|
||||
errors.push('Missing type');
|
||||
}
|
||||
if (!msg.payload || !msg.payload.summary) {
|
||||
errors.push('Missing payload.summary');
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
function validateDevId(devId, devModuleMap) {
|
||||
return devModuleMap.mappings && devModuleMap.mappings[devId];
|
||||
}
|
||||
|
||||
function processProgressUpdate(msg) {
|
||||
// Update task-queue
|
||||
const taskQueuePath = path.join(MEMORY, msg.dev_id, 'task-queue.json');
|
||||
if (fs.existsSync(taskQueuePath)) {
|
||||
const taskQueue = JSON.parse(fs.readFileSync(taskQueuePath, 'utf8'));
|
||||
taskQueue.tasks.push({
|
||||
type: 'progress-update',
|
||||
broadcast_ref: msg.payload.broadcast_ref || null,
|
||||
summary: msg.payload.summary,
|
||||
timestamp: msg.timestamp,
|
||||
status: 'received'
|
||||
});
|
||||
taskQueue.last_broadcast_ref = msg.payload.broadcast_ref || taskQueue.last_broadcast_ref;
|
||||
fs.writeFileSync(taskQueuePath, JSON.stringify(taskQueue, null, 2) + '\n');
|
||||
writeLog('INFO', `Updated task-queue for ${msg.dev_id}`);
|
||||
}
|
||||
|
||||
// Generate outbox broadcast
|
||||
const broadcastId = `GRID-BC-${getDateStr()}-${msg.dev_id}-001`;
|
||||
const broadcast = {
|
||||
schema_version: '1.0',
|
||||
broadcast_id: broadcastId,
|
||||
generated_at: getTimestamp(),
|
||||
generated_by: 'zhuyuan-workflow',
|
||||
dev_id: msg.dev_id,
|
||||
persona_id: msg.persona_id,
|
||||
type: 'task-directive',
|
||||
system_format: {
|
||||
context_update: {
|
||||
previous_step_verified: true,
|
||||
source_message: msg.message_id
|
||||
}
|
||||
},
|
||||
human_readable: `收到进度更新: ${msg.payload.summary}`
|
||||
};
|
||||
|
||||
const outboxPath = path.join(OUTBOX_LATEST, `${msg.dev_id}.json`);
|
||||
fs.writeFileSync(outboxPath, JSON.stringify(broadcast, null, 2) + '\n');
|
||||
writeLog('INFO', `Generated broadcast ${broadcastId} for ${msg.dev_id}`);
|
||||
}
|
||||
|
||||
function processDevLog(msg) {
|
||||
// Archive to interactions
|
||||
const dateStr = getDateStr();
|
||||
const interDir = path.join(INTERACTIONS, msg.dev_id);
|
||||
if (!fs.existsSync(interDir)) {
|
||||
fs.mkdirSync(interDir, { recursive: true });
|
||||
}
|
||||
|
||||
const sessionId = (msg.context && msg.context.session_id) || 'unknown';
|
||||
const interFile = path.join(interDir, `${dateStr}-${sessionId}.jsonl`);
|
||||
const record = {
|
||||
schema_version: '1.0',
|
||||
timestamp: msg.timestamp,
|
||||
dev_id: msg.dev_id,
|
||||
persona_id: msg.persona_id,
|
||||
session_id: sessionId,
|
||||
role: 'system',
|
||||
content: msg.payload.summary,
|
||||
metadata: { topic: 'dev-log' }
|
||||
};
|
||||
fs.appendFileSync(interFile, JSON.stringify(record) + '\n');
|
||||
|
||||
// Update dev-profile
|
||||
const profilePath = path.join(MEMORY, msg.dev_id, 'dev-profile.json');
|
||||
if (fs.existsSync(profilePath)) {
|
||||
const profile = JSON.parse(fs.readFileSync(profilePath, 'utf8'));
|
||||
profile.growth_trajectory.push({
|
||||
timestamp: msg.timestamp,
|
||||
event: msg.payload.summary
|
||||
});
|
||||
fs.writeFileSync(profilePath, JSON.stringify(profile, null, 2) + '\n');
|
||||
}
|
||||
|
||||
writeLog('INFO', `Archived dev-log for ${msg.dev_id}`);
|
||||
}
|
||||
|
||||
function processInteractionDump(msg) {
|
||||
// Write to interactions
|
||||
const dateStr = getDateStr();
|
||||
const interDir = path.join(INTERACTIONS, msg.dev_id);
|
||||
if (!fs.existsSync(interDir)) {
|
||||
fs.mkdirSync(interDir, { recursive: true });
|
||||
}
|
||||
|
||||
const sessionId = (msg.context && msg.context.session_id) || 'unknown';
|
||||
const interFile = path.join(interDir, `${dateStr}-${sessionId}.jsonl`);
|
||||
const record = {
|
||||
schema_version: '1.0',
|
||||
timestamp: msg.timestamp,
|
||||
dev_id: msg.dev_id,
|
||||
persona_id: msg.persona_id,
|
||||
session_id: sessionId,
|
||||
role: 'system',
|
||||
content: msg.payload.summary,
|
||||
metadata: { topic: 'interaction-dump' }
|
||||
};
|
||||
fs.appendFileSync(interFile, JSON.stringify(record) + '\n');
|
||||
|
||||
// Append to training-lake/raw
|
||||
const batchFile = path.join(TRAINING_RAW, `${dateStr}-batch.jsonl`);
|
||||
const sample = {
|
||||
schema_version: '1.0',
|
||||
sample_id: `${msg.message_id}-sample`,
|
||||
source_session: sessionId,
|
||||
dev_id: msg.dev_id,
|
||||
persona_id: msg.persona_id,
|
||||
created_at: msg.timestamp,
|
||||
turns: [{ role: 'system', content: msg.payload.summary, timestamp: msg.timestamp }],
|
||||
curated: false
|
||||
};
|
||||
fs.appendFileSync(batchFile, JSON.stringify(sample) + '\n');
|
||||
|
||||
writeLog('INFO', `Archived interaction-dump for ${msg.dev_id}, appended to training-lake`);
|
||||
}
|
||||
|
||||
function processHelpRequest(msg) {
|
||||
// Mark as P0 and generate immediate response broadcast
|
||||
const broadcastId = `GRID-BC-${getDateStr()}-${msg.dev_id}-P0`;
|
||||
const broadcast = {
|
||||
schema_version: '1.0',
|
||||
broadcast_id: broadcastId,
|
||||
generated_at: getTimestamp(),
|
||||
generated_by: 'zhuyuan-workflow',
|
||||
dev_id: msg.dev_id,
|
||||
persona_id: msg.persona_id,
|
||||
type: 'system-notice',
|
||||
system_format: {
|
||||
notice_type: 'help-response',
|
||||
original_request: msg.message_id,
|
||||
priority: 'P0'
|
||||
},
|
||||
human_readable: `收到求助请求: ${msg.payload.summary}。铸渊已标记为 P0 优先处理。`
|
||||
};
|
||||
|
||||
const outboxPath = path.join(OUTBOX_LATEST, `${msg.dev_id}.json`);
|
||||
fs.writeFileSync(outboxPath, JSON.stringify(broadcast, null, 2) + '\n');
|
||||
writeLog('WARN', `P0 help-request from ${msg.dev_id}: ${msg.payload.summary}`);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
writeLog('INFO', '=== Grid-DB Inbox Processor Started ===');
|
||||
|
||||
// Load dev-module-map for validation
|
||||
const devModuleMapPath = path.join(RULES, 'dev-module-map.json');
|
||||
if (!fs.existsSync(devModuleMapPath)) {
|
||||
writeLog('ERROR', 'dev-module-map.json not found in rules/');
|
||||
process.exit(1);
|
||||
}
|
||||
const devModuleMap = JSON.parse(fs.readFileSync(devModuleMapPath, 'utf8'));
|
||||
|
||||
// Scan inbox
|
||||
const inboxFiles = fs.readdirSync(INBOX)
|
||||
.filter(f => f.endsWith('.json'));
|
||||
|
||||
if (inboxFiles.length === 0) {
|
||||
writeLog('INFO', 'No messages in inbox');
|
||||
return;
|
||||
}
|
||||
|
||||
writeLog('INFO', `Found ${inboxFiles.length} message(s) in inbox`);
|
||||
|
||||
let processed = 0;
|
||||
let rejected = 0;
|
||||
|
||||
for (const filename of inboxFiles) {
|
||||
const inboxPath = path.join(INBOX, filename);
|
||||
let msg;
|
||||
|
||||
try {
|
||||
msg = JSON.parse(fs.readFileSync(inboxPath, 'utf8'));
|
||||
} catch (err) {
|
||||
writeLog('ERROR', `Failed to parse ${filename}: ${err.message}`);
|
||||
rejected++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Validate
|
||||
const errors = validateMessage(msg, filename);
|
||||
if (errors.length > 0) {
|
||||
writeLog('ERROR', `Validation failed for ${filename}: ${errors.join(', ')}`);
|
||||
rejected++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Validate dev_id
|
||||
if (!validateDevId(msg.dev_id, devModuleMap)) {
|
||||
writeLog('ERROR', `Unknown dev_id ${msg.dev_id} in ${filename}`);
|
||||
rejected++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Move to processing
|
||||
const processingPath = path.join(PROCESSING, filename);
|
||||
fs.renameSync(inboxPath, processingPath);
|
||||
writeLog('INFO', `Processing ${filename} (type: ${msg.type})`);
|
||||
|
||||
// Route by type
|
||||
try {
|
||||
switch (msg.type) {
|
||||
case 'progress-update':
|
||||
processProgressUpdate(msg);
|
||||
break;
|
||||
case 'dev-log':
|
||||
processDevLog(msg);
|
||||
break;
|
||||
case 'help-request':
|
||||
processHelpRequest(msg);
|
||||
break;
|
||||
case 'interaction-dump':
|
||||
processInteractionDump(msg);
|
||||
break;
|
||||
case 'syslog':
|
||||
writeLog('INFO', `Syslog message from ${msg.dev_id}: forwarding to standard pipeline`);
|
||||
break;
|
||||
default:
|
||||
writeLog('WARN', `Unknown message type: ${msg.type}`);
|
||||
}
|
||||
|
||||
// Archive processed message
|
||||
const archiveDir = path.join(OUTBOX_ARCHIVE, getDateStr());
|
||||
if (!fs.existsSync(archiveDir)) {
|
||||
fs.mkdirSync(archiveDir, { recursive: true });
|
||||
}
|
||||
fs.renameSync(processingPath, path.join(archiveDir, filename));
|
||||
processed++;
|
||||
} catch (err) {
|
||||
writeLog('ERROR', `Error processing ${filename}: ${err.message}`);
|
||||
// Move back to inbox for retry
|
||||
if (fs.existsSync(processingPath)) {
|
||||
fs.renameSync(processingPath, inboxPath);
|
||||
}
|
||||
rejected++;
|
||||
}
|
||||
}
|
||||
|
||||
writeLog('INFO', `=== Processing complete: ${processed} processed, ${rejected} rejected ===`);
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error('[process-inbox] Fatal error:', err.message);
|
||||
process.exit(1);
|
||||
});
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
* scripts/grid-db/sync-griddb-to-notion.js
|
||||
*
|
||||
* Grid-DB → Notion 增量回传脚本
|
||||
*
|
||||
* 职责:
|
||||
* - 检测 grid-db/memory/ 中变更的文件(排除 brain-mirror.json)
|
||||
* - 将 session-context, task-queue, dev-profile, persona-growth 的增量变化回传到 Notion
|
||||
* - task-queue: 追加制(新任务追加,已有任务只改状态不删除)
|
||||
* - dev-profile / persona-growth: 只追加不覆盖
|
||||
*
|
||||
* 环境变量:
|
||||
* - NOTION_API_TOKEN: Notion API 密钥
|
||||
*
|
||||
* 守护: PER-ZY001 铸渊
|
||||
* 系统: SYS-GLW-0001
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { execSync } = require('child_process');
|
||||
|
||||
const GRID_DB_MEMORY = path.join(__dirname, '../../grid-db/memory');
|
||||
|
||||
async function main() {
|
||||
const notionToken = process.env.NOTION_API_TOKEN;
|
||||
|
||||
if (!notionToken) {
|
||||
console.log('[sync-griddb-to-notion] NOTION_API_TOKEN not set, skipping sync');
|
||||
return;
|
||||
}
|
||||
|
||||
// Detect changed files (passed from workflow or detect via git diff)
|
||||
let changedFiles;
|
||||
try {
|
||||
const diff = execSync('git diff --name-only HEAD~1 HEAD -- grid-db/memory/', { encoding: 'utf8' });
|
||||
changedFiles = diff.trim().split('\n')
|
||||
.filter(f => f && !f.includes('brain-mirror.json'));
|
||||
} catch {
|
||||
console.log('[sync-griddb-to-notion] No changes detected');
|
||||
return;
|
||||
}
|
||||
|
||||
if (changedFiles.length === 0) {
|
||||
console.log('[sync-griddb-to-notion] No eligible changes to sync');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`[sync-griddb-to-notion] Processing ${changedFiles.length} changed files:`);
|
||||
|
||||
for (const file of changedFiles) {
|
||||
const fullPath = path.join(__dirname, '../..', file);
|
||||
if (!fs.existsSync(fullPath)) {
|
||||
console.log(` [skip] ${file} (deleted)`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const data = JSON.parse(fs.readFileSync(fullPath, 'utf8'));
|
||||
const fileName = path.basename(file);
|
||||
const devDir = path.basename(path.dirname(file));
|
||||
|
||||
console.log(` [sync] ${devDir}/${fileName}`);
|
||||
|
||||
// TODO: Implement actual Notion API write
|
||||
// - session-context.json → update Notion page property
|
||||
// - task-queue.json → append/update tasks in Notion database
|
||||
// - dev-profile.json → append growth data
|
||||
// - persona-growth.json → append adaptation log
|
||||
}
|
||||
|
||||
console.log('[sync-griddb-to-notion] Sync complete');
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error('[sync-griddb-to-notion] Error:', err.message);
|
||||
process.exit(1);
|
||||
});
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* scripts/grid-db/sync-notion-brain-mirror.js
|
||||
*
|
||||
* Notion → Grid-DB brain-mirror.json 同步脚本
|
||||
*
|
||||
* 职责:
|
||||
* - 从 Notion 天眼注册表拉取每个活跃人格体的核心大脑数据
|
||||
* - 写入对应的 grid-db/memory/DEV-XXX/brain-mirror.json
|
||||
* - Notion 永远覆盖仓库(单向同步)
|
||||
*
|
||||
* 环境变量:
|
||||
* - NOTION_API_TOKEN: Notion API 密钥
|
||||
*
|
||||
* 守护: PER-ZY001 铸渊
|
||||
* 系统: SYS-GLW-0001
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const GRID_DB_MEMORY = path.join(__dirname, '../../grid-db/memory');
|
||||
const DEV_MODULE_MAP = path.join(__dirname, '../../grid-db/rules/dev-module-map.json');
|
||||
|
||||
async function main() {
|
||||
const notionToken = process.env.NOTION_API_TOKEN;
|
||||
|
||||
if (!notionToken) {
|
||||
console.log('[sync-notion-brain-mirror] NOTION_API_TOKEN not set, skipping sync');
|
||||
return;
|
||||
}
|
||||
|
||||
// Load dev-module-map to know which DEVs are active
|
||||
const devMap = JSON.parse(fs.readFileSync(DEV_MODULE_MAP, 'utf8'));
|
||||
const activeDev = Object.entries(devMap.mappings)
|
||||
.filter(([, info]) => info.active && info.persona_id);
|
||||
|
||||
console.log(`[sync-notion-brain-mirror] Found ${activeDev.length} active developers`);
|
||||
|
||||
for (const [devId, info] of activeDev) {
|
||||
const mirrorPath = path.join(GRID_DB_MEMORY, devId, 'brain-mirror.json');
|
||||
|
||||
if (!fs.existsSync(mirrorPath)) {
|
||||
console.log(`[sync-notion-brain-mirror] Skipping ${devId}: no memory directory`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: Replace with actual Notion API call when NOTION_API_TOKEN is configured
|
||||
// For now, update the sync status timestamp
|
||||
const existing = JSON.parse(fs.readFileSync(mirrorPath, 'utf8'));
|
||||
|
||||
// Only update if we got actual data from Notion (placeholder for real API)
|
||||
console.log(`[sync-notion-brain-mirror] ${devId} (${info.persona_name}): ready for Notion sync`);
|
||||
}
|
||||
|
||||
console.log('[sync-notion-brain-mirror] Sync complete');
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error('[sync-notion-brain-mirror] Error:', err.message);
|
||||
process.exit(1);
|
||||
});
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* scripts/grid-db/sync-notion-rules.js
|
||||
*
|
||||
* Notion → Grid-DB rules/ 同步脚本
|
||||
*
|
||||
* 职责:
|
||||
* - 从 Notion 拉取广播模板、编号体系、活跃广播等规则数据
|
||||
* - 写入 grid-db/rules/ 目录
|
||||
* - Notion 永远覆盖仓库(单向同步)
|
||||
*
|
||||
* 环境变量:
|
||||
* - NOTION_API_TOKEN: Notion API 密钥
|
||||
*
|
||||
* 守护: PER-ZY001 铸渊
|
||||
* 系统: SYS-GLW-0001
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const RULES_DIR = path.join(__dirname, '../../grid-db/rules');
|
||||
|
||||
async function main() {
|
||||
const notionToken = process.env.NOTION_API_TOKEN;
|
||||
|
||||
if (!notionToken) {
|
||||
console.log('[sync-notion-rules] NOTION_API_TOKEN not set, skipping sync');
|
||||
return;
|
||||
}
|
||||
|
||||
const ruleFiles = [
|
||||
'broadcast-templates.json',
|
||||
'dev-module-map.json',
|
||||
'id-ecosystem.json',
|
||||
'active-broadcasts.json'
|
||||
];
|
||||
|
||||
for (const file of ruleFiles) {
|
||||
const filePath = path.join(RULES_DIR, file);
|
||||
if (fs.existsSync(filePath)) {
|
||||
console.log(`[sync-notion-rules] ${file}: ready for Notion sync`);
|
||||
// TODO: Replace with actual Notion API call
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[sync-notion-rules] Rules sync complete');
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error('[sync-notion-rules] Error:', err.message);
|
||||
process.exit(1);
|
||||
});
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
/**
|
||||
* scripts/grid-db/write-code-check-result.js
|
||||
*
|
||||
* 代码校验结果写入 Grid-DB
|
||||
*
|
||||
* 用途:在 CI 代码校验完成后,自动向 grid-db 写入进度消息。
|
||||
* 被现有 contract-check workflow 的末尾 step 调用。
|
||||
*
|
||||
* 参数:
|
||||
* --dev-id=DEV-XXX 开发者编号
|
||||
* --result=pass|fail 校验结果
|
||||
* --files-checked=N 检查的文件数
|
||||
*
|
||||
* 守护: PER-ZY001 铸渊
|
||||
* 系统: SYS-GLW-0001
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const INBOX = path.join(__dirname, '../../grid-db/inbox');
|
||||
|
||||
function parseArgs() {
|
||||
const args = {};
|
||||
process.argv.slice(2).forEach(arg => {
|
||||
const [key, value] = arg.replace(/^--/, '').split('=');
|
||||
if (key && value) {
|
||||
args[key] = value;
|
||||
}
|
||||
});
|
||||
return args;
|
||||
}
|
||||
|
||||
function getDateStr() {
|
||||
return new Date().toISOString().slice(0, 10).replace(/-/g, '');
|
||||
}
|
||||
|
||||
function getTimeStr() {
|
||||
return new Date().toISOString().slice(11, 19).replace(/:/g, '');
|
||||
}
|
||||
|
||||
function main() {
|
||||
const args = parseArgs();
|
||||
const devId = args['dev-id'];
|
||||
const result = args['result'] || 'unknown';
|
||||
const filesChecked = args['files-checked'] || '0';
|
||||
|
||||
if (!devId || !/^DEV-\d{3}$/.test(devId)) {
|
||||
console.error('[write-code-check-result] Invalid or missing --dev-id');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const dateStr = getDateStr();
|
||||
const timeStr = getTimeStr();
|
||||
const messageId = `${dateStr}-${timeStr}-${devId}-code-check`;
|
||||
|
||||
const message = {
|
||||
schema_version: '1.0',
|
||||
message_id: messageId,
|
||||
timestamp: new Date().toISOString(),
|
||||
source: 'workflow',
|
||||
dev_id: devId,
|
||||
persona_id: 'PER-ZY001',
|
||||
type: 'progress-update',
|
||||
priority: result === 'fail' ? 'P1' : 'info',
|
||||
payload: {
|
||||
summary: `Code check ${result}: ${filesChecked} files checked for ${devId}`,
|
||||
detail: {
|
||||
result: result,
|
||||
files_checked: parseInt(filesChecked, 10),
|
||||
triggered_by: 'contract-check-workflow'
|
||||
},
|
||||
code_refs: [],
|
||||
broadcast_ref: null,
|
||||
emotion_markers: {}
|
||||
},
|
||||
context: {
|
||||
session_id: `ci-${dateStr}-${timeStr}`,
|
||||
interaction_count: 0,
|
||||
persona_state: {
|
||||
engagement_level: 'automated',
|
||||
teaching_mode: 'code-review'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const filename = `${messageId}.json`;
|
||||
const filePath = path.join(INBOX, filename);
|
||||
|
||||
fs.writeFileSync(filePath, JSON.stringify(message, null, 2) + '\n');
|
||||
console.log(`[write-code-check-result] Written ${filename} to inbox`);
|
||||
}
|
||||
|
||||
main();
|
||||
Loading…
Reference in New Issue