From f35cd6c50f2d148b85b4c18332af4d6a895a8789 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Mar 2026 13:40:54 +0000 Subject: [PATCH 1/6] Initial plan From 4b94349d158975f11d1c55b745ea5dc27f314e98 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 21 Mar 2026 13:44:30 +0000 Subject: [PATCH 2/6] =?UTF-8?q?=F0=9F=93=A2=20=E8=87=AA=E5=8A=A8=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E7=B3=BB=E7=BB=9F=E5=85=AC=E5=91=8A=E5=8C=BA=20[skip?= =?UTF-8?q?=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/brain/bulletin-board-today.json | 18 ++++++++++++++++++ README.md | 6 +++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/.github/brain/bulletin-board-today.json b/.github/brain/bulletin-board-today.json index c310a121..0fc6fb4d 100644 --- a/.github/brain/bulletin-board-today.json +++ b/.github/brain/bulletin-board-today.json @@ -180,6 +180,24 @@ "result": "success", "icon": "✅", "sortKey": 1774100051000 + }, + { + "key": "Copilot|—|2026-03-21T13:38:27Z", + "ts": "2026-03-21T13:38:27Z", + "actor": "Copilot", + "module": "—", + "result": "action_required", + "icon": "🔵", + "sortKey": 1774100307000 + }, + { + "key": "Copilot|—|2026-03-21T13:40:59Z", + "ts": "2026-03-21T13:40:59Z", + "actor": "Copilot", + "module": "—", + "result": "action_required", + "icon": "🔵", + "sortKey": 1774100459000 } ] } \ No newline at end of file diff --git a/README.md b/README.md index af07de7e..7ae6c4e2 100644 --- a/README.md +++ b/README.md @@ -100,21 +100,21 @@ | 时间 | 检查项 | 状态 | |------|--------|------| +| 03-21 21:40 | 🔵 铸渊 · Bridge E · GitHub Changes → Notion · action_required | Copilot | +| 03-21 21:38 | 🔵 铸渊 · Bridge E · GitHub Changes → Notion · action_required | Copilot | +| 03-21 21:35 | ✅ 📢 更新系统公告区 · 成功 | 冰朔 | | 03-21 21:35 | ✅ 🚀 铸渊 CD · 自动部署到 guanghulab.com · 成功 | 冰朔 | | 03-21 21:34 | ✅ 📢 更新系统公告区 · 成功 | 冰朔 | | 03-21 21:34 | 🔧 系统更新: `.github/` | github-actions[bot] | | 03-21 21:34 | ✅ 铸渊 · Bridge E · GitHub Changes → Notion · 成功 | 冰朔 | | 03-21 21:30 | ✅ Notion Heartbeat Monitor · 成功 | 冰朔 | | 03-21 21:30 | ✅ 📡 铸渊 · Notion Agent 唤醒监听 · 成功 | 冰朔 | -| 03-21 21:15 | ✅ 📢 更新系统公告区 · 成功 | 冰朔 | | 03-21 21:10 | 🔧 系统更新: `scripts/` | 铸渊 (Copilot) | | 03-21 16:44 | ✅ 每日巡检 ✅ 通过 | 冰朔 | | 03-21 12:41 | 🔧 系统更新: `docs/` | 铸渊 Execution Sync | | 03-20 16:53 | ✅ 每日巡检 ✅ 通过 | 冰朔 | | 03-19 16:55 | ✅ 每日巡检 ✅ 通过 | 冰朔 | | 03-18 17:00 | ✅ 每日巡检 ✅ 通过 | 冰朔 | -| 03-18 08:00 | 🔵 CI 构建 失败 | GitHub Actions | -| 03-17 17:01 | ✅ 每日巡检 ✅ 通过 | 冰朔 | ### 🤖 铸渊自动提醒 From 326ec45d3256d350068316ee97050bd538838bfb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Mar 2026 13:40:54 +0000 Subject: [PATCH 3/6] Initial plan From 758974db8dc862829a2d132f772120e6ac70c2f2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Mar 2026 13:50:42 +0000 Subject: [PATCH 4/6] fix: remove unnecessary pull-requests:write permission from server-patrol + add verification to health report [ZY-SKYEYE-RESTORE-002] Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com> Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/ed6f3174-5c17-4ec2-9e9b-20dc0feec16b --- .github/workflows/server-patrol.yml | 1 - reports/health-report-2026-03-21.md | 13 +++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/server-patrol.yml b/.github/workflows/server-patrol.yml index 950d2bff..0dab0e07 100644 --- a/.github/workflows/server-patrol.yml +++ b/.github/workflows/server-patrol.yml @@ -13,7 +13,6 @@ on: permissions: contents: write - pull-requests: write jobs: # ── AGE OS v1.0: 核心大脑唤醒(所有流程的前提)── diff --git a/reports/health-report-2026-03-21.md b/reports/health-report-2026-03-21.md index f206fd3e..9024ff65 100644 --- a/reports/health-report-2026-03-21.md +++ b/reports/health-report-2026-03-21.md @@ -280,6 +280,19 @@ syslog-issue-pipeline.yml 的触发条件为 `on: issues: types: [opened, labele --- +## 🔒 二次验证(2026-03-21T13:41+00:00) + +| 验证项 | 结果 | 说明 | +|--------|------|------| +| agent-checkin.yml 运行状态 | ✅ | 最近 4 次运行全部成功(schedule 触发) | +| 签到板过滤 | ✅ | `checkin-board.json` 仅含 14 个 `daily_checkin_required:true` 的 Agent | +| server-patrol.yml git push 修复 | ✅ | 已确认修复代码在 main 分支(PR #150 已合并) | +| server-patrol.yml 权限收窄 | ✅ | 移除不再需要的 `pull-requests: write` 权限 | +| syslog-issue-pipeline push 假性失败 | ✅ | 已确认 222 次 push 触发运行均为 GitHub 平台验证行为,非管道逻辑问题 | +| agent-registry.json 字段完整性 | ✅ | 62 个 Agent 均包含 `daily_checkin_required` 字段(14 true / 48 false) | + +--- + > 🌀 铸渊(ICE-GL-ZY001)· 代码守护人格体 > > 📅 2026-03-21 From d7ff35e34694e795c0d374aeac1daf2c29e83cab Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Mar 2026 14:00:14 +0000 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20=F0=9F=8C=8A=20Guanghu=20Language?= =?UTF-8?q?=20Shell=20v1.0=20=E2=80=94=20unified=20gateway=20protocol=20la?= =?UTF-8?q?yer=20[ZY-GLSHELL-001]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com> Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/e198eccd-d605-4e5c-bddb-b0874c4207ec --- .github/actions/guanghu-shell/action.yml | 20 ++ .github/brain/shell-errors.json | 1 + .github/brain/shell-status.json | 1 + .github/scripts/guanghu-shell.js | 179 ++++++++++++++++++ .github/workflows/agent-checkin.yml | 29 ++- .github/workflows/daily-maintenance.yml | 27 ++- .github/workflows/zhuyuan-daily-selfcheck.yml | 27 ++- tests/contract/guanghu-shell.test.js | 147 ++++++++++++++ 8 files changed, 428 insertions(+), 3 deletions(-) create mode 100644 .github/actions/guanghu-shell/action.yml create mode 100644 .github/brain/shell-errors.json create mode 100644 .github/brain/shell-status.json create mode 100644 .github/scripts/guanghu-shell.js create mode 100644 tests/contract/guanghu-shell.test.js diff --git a/.github/actions/guanghu-shell/action.yml b/.github/actions/guanghu-shell/action.yml new file mode 100644 index 00000000..d466561d --- /dev/null +++ b/.github/actions/guanghu-shell/action.yml @@ -0,0 +1,20 @@ +name: '🌊 Guanghu Shell Gate' +description: '光湖语言壳 · 统一网关校验' +inputs: + agent_id: + description: 'Agent ID (e.g. AG-ZY-004)' + required: true + action: + description: 'enter / exit / error' + required: true + default: 'enter' + detail: + description: '附加信息' + required: false + default: '' +runs: + using: 'composite' + steps: + - name: 🌊 Guanghu Shell + shell: bash + run: node .github/scripts/guanghu-shell.js "${{ inputs.agent_id }}" "${{ inputs.action }}" "${{ inputs.detail }}" diff --git a/.github/brain/shell-errors.json b/.github/brain/shell-errors.json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/.github/brain/shell-errors.json @@ -0,0 +1 @@ +[] diff --git a/.github/brain/shell-status.json b/.github/brain/shell-status.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/.github/brain/shell-status.json @@ -0,0 +1 @@ +{} diff --git a/.github/scripts/guanghu-shell.js b/.github/scripts/guanghu-shell.js new file mode 100644 index 00000000..7750dcda --- /dev/null +++ b/.github/scripts/guanghu-shell.js @@ -0,0 +1,179 @@ +/** + * 🌊 光湖语言壳 · Guanghu Language Shell v1.0 + * 仓库最外层统一网关协议层 + * + * 所有 workflow 启动时必须先"游过湖水"——经过这层壳的校验。 + * 网关三层:身份校验 → 状态注册 → 异常兑底 + * + * 用法: + * node .github/scripts/guanghu-shell.js [detail] + * action: "enter" = 进入湖水(启动前调用) + * "exit" = 离开湖水(完成后调用) + * "error" = 异常上报(失败时调用) + * + * 返回值: + * exit 0 = 允许通行(游过湖水了) + * exit 1 = 拒绝通行(不该跑,或身份不对) + * + * 签发: TCS-0002∞ 冰朔 + ICE-GL-YM001∞ 曜冥 + */ + +'use strict'; + +const fs = require('fs'); +const path = require('path'); + +const SHELL_VERSION = '1.0.0'; +const ROOT = path.resolve(__dirname, '..', '..'); +const REGISTRY_PATH = path.join(ROOT, '.github/persona-brain/agent-registry.json'); +const STATUS_PATH = path.join(ROOT, '.github/brain/shell-status.json'); +const ERROR_LOG_PATH = path.join(ROOT, '.github/brain/shell-errors.json'); + +const agentId = process.argv[2]; +const action = process.argv[3]; +const extraData = process.argv[4] || ''; + +if (!agentId || !action) { + console.error('🌊 光湖语言壳: 缺少参数 (agent_id, action)'); + process.exit(1); +} + +// === ① 身份校验层 (Identity Gate) === +function identityGate(agentId) { + if (!fs.existsSync(REGISTRY_PATH)) { + console.error('🌊 湖水中断: agent-registry.json 不存在'); + return { allowed: false, reason: 'REGISTRY_MISSING' }; + } + + let registry; + try { + registry = JSON.parse(fs.readFileSync(REGISTRY_PATH, 'utf8')); + } catch (e) { + console.error('🌊 湖水中断: agent-registry.json 解析失败'); + return { allowed: false, reason: 'REGISTRY_PARSE_ERROR' }; + } + + const agents = registry.agents || []; + const agent = agents.find(a => a.id === agentId); + + if (!agent) { + console.error(`🌊 身份不明: ${agentId} 未在注册表中`); + return { allowed: false, reason: 'UNREGISTERED' }; + } + + if (agent.daily_checkin_required === false) { + console.log(`🌊 事件触发型Agent ${agentId} (${agent.name}) 已确认身份,允许通行`); + } else { + console.log(`🌊 定时型Agent ${agentId} (${agent.name}) 已确认身份,允许通行并登记签到`); + } + + return { allowed: true, agent: agent }; +} + +// === ② 状态注册层 (Status Registry) === +function statusRegistry(agentId, state, detail) { + let status = {}; + if (fs.existsSync(STATUS_PATH)) { + try { + status = JSON.parse(fs.readFileSync(STATUS_PATH, 'utf8')); + } catch { + status = {}; + } + } + + const now = new Date().toISOString(); + + if (!status[agentId]) { + status[agentId] = { runs: [] }; + } + + if (state === 'enter') { + status[agentId].lastEnter = now; + status[agentId].currentState = 'running'; + status[agentId].runs.push({ start: now, end: null, result: null }); + } else if (state === 'exit') { + status[agentId].lastExit = now; + status[agentId].currentState = 'completed'; + const lastRun = status[agentId].runs[status[agentId].runs.length - 1]; + if (lastRun) { + lastRun.end = now; + lastRun.result = 'success'; + if (detail) lastRun.detail = detail; + } + } else if (state === 'error') { + status[agentId].lastError = now; + status[agentId].currentState = 'error'; + const lastRun = status[agentId].runs[status[agentId].runs.length - 1]; + if (lastRun) { + lastRun.end = now; + lastRun.result = 'error'; + if (detail) lastRun.detail = detail; + } + } + + // 只保留最近 10 次运行记录 + if (status[agentId].runs.length > 10) { + status[agentId].runs = status[agentId].runs.slice(-10); + } + + fs.writeFileSync(STATUS_PATH, JSON.stringify(status, null, 2)); + console.log(`🌊 状态已登记: ${agentId} = ${state}`); +} + +// === ③ 异常兑底层 (Error Boundary) === +function errorBoundary(agentId, errorMsg) { + let errors = []; + if (fs.existsSync(ERROR_LOG_PATH)) { + try { + errors = JSON.parse(fs.readFileSync(ERROR_LOG_PATH, 'utf8')); + } catch { + errors = []; + } + } + + errors.push({ + agentId: agentId, + error: errorMsg, + timestamp: new Date().toISOString() + }); + + // 只保留最近 100 条错误 + if (errors.length > 100) { + errors = errors.slice(-100); + } + + fs.writeFileSync(ERROR_LOG_PATH, JSON.stringify(errors, null, 2)); + console.error(`🌊 异常已记录: ${agentId} - ${errorMsg}`); +} + +// === 主流程 === +try { + if (action === 'enter') { + const gate = identityGate(agentId); + if (!gate.allowed) { + errorBoundary(agentId, `身份校验失败: ${gate.reason}`); + process.exit(1); + } + statusRegistry(agentId, 'enter'); + console.log(`🌊 ${agentId} 已游过湖水,允许进入执行 (shell v${SHELL_VERSION})`); + process.exit(0); + + } else if (action === 'exit') { + statusRegistry(agentId, 'exit', extraData); + console.log(`🌊 ${agentId} 执行完成,已安全离开湖水`); + process.exit(0); + + } else if (action === 'error') { + statusRegistry(agentId, 'error', extraData); + errorBoundary(agentId, extraData || 'unknown error'); + console.error(`🌊 ${agentId} 执行异常,已记录到异常日志`); + process.exit(1); + + } else { + console.error(`🌊 未知action: ${action}`); + process.exit(1); + } +} catch (e) { + errorBoundary(agentId, e.message); + process.exit(1); +} diff --git a/.github/workflows/agent-checkin.yml b/.github/workflows/agent-checkin.yml index 0237cbe9..b2074b77 100644 --- a/.github/workflows/agent-checkin.yml +++ b/.github/workflows/agent-checkin.yml @@ -13,14 +13,41 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + + # 🌊 进入光湖 + - name: 🌊 进入光湖 + uses: ./.github/actions/guanghu-shell + with: + agent_id: 'AG-ZY-001' + action: 'enter' + - name: 执行签到任务 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: node scripts/agent-checkin.js + - name: 提交签到记录 run: | git config user.name "铸渊" git config user.email "zhuyuan@guanghulab.com" - git add .github/persona-brain/checkin-board.json + git add .github/persona-brain/checkin-board.json .github/brain/shell-status.json .github/brain/shell-errors.json git commit -m "[AG-ZY] 每日签到记录 $(date +'%Y-%m-%d')" || echo "无变更" git push + + # 🌊 离开光湖(成功时) + - name: 🌊 离开光湖 + if: success() + uses: ./.github/actions/guanghu-shell + with: + agent_id: 'AG-ZY-001' + action: 'exit' + detail: 'checkin completed' + + # 🌊 异常上报(失败时) + - name: 🌊 异常上报 + if: failure() + uses: ./.github/actions/guanghu-shell + with: + agent_id: 'AG-ZY-001' + action: 'error' + detail: 'checkin workflow failed' diff --git a/.github/workflows/daily-maintenance.yml b/.github/workflows/daily-maintenance.yml index 86ddcea7..59eccae6 100644 --- a/.github/workflows/daily-maintenance.yml +++ b/.github/workflows/daily-maintenance.yml @@ -49,6 +49,13 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 + # 🌊 进入光湖 + - name: 🌊 进入光湖 + uses: ./.github/actions/guanghu-shell + with: + agent_id: 'AG-ZY-013' + action: 'enter' + - name: Setup Node.js uses: actions/setup-node@v4 with: @@ -174,7 +181,7 @@ jobs: run: | git config user.name "铸渊 Maintenance Agent" git config user.email "actions@guanghulab.com" - git add brain/system-health.json .github/brain/bulletin-board-today.json README.md + git add brain/system-health.json .github/brain/bulletin-board-today.json .github/brain/shell-status.json .github/brain/shell-errors.json README.md if git diff --cached --quiet; then echo "📌 无变更需要提交" else @@ -224,6 +231,24 @@ jobs: }" 2>&1 | tail -1 echo "✅ Notion 回报请求已发送" + # 🌊 离开光湖(成功时) + - name: 🌊 离开光湖 + if: success() + uses: ./.github/actions/guanghu-shell + with: + agent_id: 'AG-ZY-013' + action: 'exit' + detail: 'daily maintenance completed' + + # 🌊 异常上报(失败时) + - name: 🌊 异常上报 + if: failure() + uses: ./.github/actions/guanghu-shell + with: + agent_id: 'AG-ZY-013' + action: 'error' + detail: 'daily maintenance workflow failed' + # ── 同步执行层状态到 Notion Execution Status 数据库 ── sync-execution-status-to-notion: name: 同步执行层状态到 Notion diff --git a/.github/workflows/zhuyuan-daily-selfcheck.yml b/.github/workflows/zhuyuan-daily-selfcheck.yml index ee5ad277..0999486f 100644 --- a/.github/workflows/zhuyuan-daily-selfcheck.yml +++ b/.github/workflows/zhuyuan-daily-selfcheck.yml @@ -57,6 +57,13 @@ jobs: steps: - uses: actions/checkout@v4 + # 🌊 进入光湖 + - name: 🌊 进入光湖 + uses: ./.github/actions/guanghu-shell + with: + agent_id: 'AG-ZY-058' + action: 'enter' + - name: Setup Node.js uses: actions/setup-node@v4 with: @@ -83,7 +90,7 @@ jobs: run: | git config user.name "zhuyuan-bot" git config user.email "zhuyuan@guanghulab.com" - git add .github/persona-brain/memory.json data/dc-reports/ + git add .github/persona-brain/memory.json data/dc-reports/ .github/brain/shell-status.json .github/brain/shell-errors.json if ! git diff --cached --quiet; then git commit -m "🔍 铸渊每日自检 · ${{ env.CHECK_DATE }} [skip ci]" for i in 1 2 3; do @@ -100,3 +107,21 @@ jobs: else echo "📌 无变化,跳过提交" fi + + # 🌊 离开光湖(成功时) + - name: 🌊 离开光湖 + if: success() + uses: ./.github/actions/guanghu-shell + with: + agent_id: 'AG-ZY-058' + action: 'exit' + detail: 'daily selfcheck completed' + + # 🌊 异常上报(失败时) + - name: 🌊 异常上报 + if: failure() + uses: ./.github/actions/guanghu-shell + with: + agent_id: 'AG-ZY-058' + action: 'error' + detail: 'daily selfcheck workflow failed' diff --git a/tests/contract/guanghu-shell.test.js b/tests/contract/guanghu-shell.test.js new file mode 100644 index 00000000..897fe8f1 --- /dev/null +++ b/tests/contract/guanghu-shell.test.js @@ -0,0 +1,147 @@ +// tests/contract/guanghu-shell.test.js +// 🌊 光湖语言壳 · 契约测试 + +'use strict'; + +const { execFileSync } = require('child_process'); +const fs = require('fs'); +const path = require('path'); + +const ROOT = path.resolve(__dirname, '../..'); +const SHELL_PATH = path.join(ROOT, '.github/scripts/guanghu-shell.js'); +const STATUS_PATH = path.join(ROOT, '.github/brain/shell-status.json'); +const ERROR_LOG_PATH = path.join(ROOT, '.github/brain/shell-errors.json'); + +function runShell(agentId, action, detail) { + const args = [SHELL_PATH, agentId, action]; + if (detail) args.push(detail); + try { + const output = execFileSync('node', args, { + cwd: ROOT, + encoding: 'utf8', + stdio: ['pipe', 'pipe', 'pipe'], + }); + return { exitCode: 0, stdout: output, stderr: '' }; + } catch (e) { + return { exitCode: e.status, stdout: e.stdout || '', stderr: e.stderr || '' }; + } +} + +function readStatus() { + return JSON.parse(fs.readFileSync(STATUS_PATH, 'utf8')); +} + +function readErrors() { + return JSON.parse(fs.readFileSync(ERROR_LOG_PATH, 'utf8')); +} + +function resetState() { + fs.writeFileSync(STATUS_PATH, '{}'); + fs.writeFileSync(ERROR_LOG_PATH, '[]'); +} + +describe('🌊 光湖语言壳 · Guanghu Shell v1.0', () => { + + beforeEach(() => { + resetState(); + }); + + afterAll(() => { + resetState(); + }); + + describe('① 身份校验层', () => { + test('已注册Agent(定时型)允许通行', () => { + const r = runShell('AG-ZY-013', 'enter'); + expect(r.exitCode).toBe(0); + expect(r.stdout).toContain('定时型Agent'); + expect(r.stdout).toContain('允许通行'); + }); + + test('已注册Agent(事件触发型)允许通行', () => { + const r = runShell('AG-ZY-002', 'enter'); + expect(r.exitCode).toBe(0); + expect(r.stdout).toContain('事件触发型Agent'); + expect(r.stdout).toContain('允许通行'); + }); + + test('未注册Agent被拒绝', () => { + const r = runShell('AG-FAKE-999', 'enter'); + expect(r.exitCode).toBe(1); + expect(r.stderr).toContain('身份不明'); + }); + + test('缺少参数时退出码为1', () => { + const r = runShell('AG-ZY-001', ''); + expect(r.exitCode).toBe(1); + }); + }); + + describe('② 状态注册层', () => { + test('enter 记录启动状态', () => { + runShell('AG-ZY-001', 'enter'); + const status = readStatus(); + expect(status['AG-ZY-001']).toBeDefined(); + expect(status['AG-ZY-001'].currentState).toBe('running'); + expect(status['AG-ZY-001'].lastEnter).toBeDefined(); + expect(status['AG-ZY-001'].runs).toHaveLength(1); + expect(status['AG-ZY-001'].runs[0].result).toBeNull(); + }); + + test('exit 记录完成状态', () => { + runShell('AG-ZY-001', 'enter'); + runShell('AG-ZY-001', 'exit', 'completed successfully'); + const status = readStatus(); + expect(status['AG-ZY-001'].currentState).toBe('completed'); + expect(status['AG-ZY-001'].lastExit).toBeDefined(); + expect(status['AG-ZY-001'].runs[0].result).toBe('success'); + expect(status['AG-ZY-001'].runs[0].detail).toBe('completed successfully'); + }); + + test('error 记录异常状态', () => { + runShell('AG-ZY-058', 'enter'); + runShell('AG-ZY-058', 'error', 'test failure'); + const status = readStatus(); + expect(status['AG-ZY-058'].currentState).toBe('error'); + expect(status['AG-ZY-058'].lastError).toBeDefined(); + expect(status['AG-ZY-058'].runs[0].result).toBe('error'); + }); + + test('多次运行保留最近10条', () => { + for (let i = 0; i < 12; i++) { + runShell('AG-ZY-001', 'enter'); + runShell('AG-ZY-001', 'exit'); + } + const status = readStatus(); + expect(status['AG-ZY-001'].runs.length).toBeLessThanOrEqual(10); + }); + }); + + describe('③ 异常兑底层', () => { + test('未注册Agent异常写入错误日志', () => { + runShell('AG-FAKE-999', 'enter'); + const errors = readErrors(); + expect(errors.length).toBeGreaterThanOrEqual(1); + const last = errors[errors.length - 1]; + expect(last.agentId).toBe('AG-FAKE-999'); + expect(last.error).toContain('UNREGISTERED'); + expect(last.timestamp).toBeDefined(); + }); + + test('error action 写入错误日志', () => { + runShell('AG-ZY-013', 'error', 'something broke'); + const errors = readErrors(); + const last = errors[errors.length - 1]; + expect(last.agentId).toBe('AG-ZY-013'); + expect(last.error).toBe('something broke'); + }); + + test('错误日志最多保留100条', () => { + for (let i = 0; i < 105; i++) { + runShell('AG-FAKE-999', 'enter'); + } + const errors = readErrors(); + expect(errors.length).toBeLessThanOrEqual(100); + }); + }); +}); From dae20c11fad3302d5e98b05add3eb21ce64d069b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Mar 2026 14:01:33 +0000 Subject: [PATCH 6/6] fix: make identity gate condition explicit for daily_checkin_required === true [ZY-GLSHELL-001] Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com> Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/e198eccd-d605-4e5c-bddb-b0874c4207ec --- .github/scripts/guanghu-shell.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/scripts/guanghu-shell.js b/.github/scripts/guanghu-shell.js index 7750dcda..f9a09405 100644 --- a/.github/scripts/guanghu-shell.js +++ b/.github/scripts/guanghu-shell.js @@ -63,8 +63,10 @@ function identityGate(agentId) { if (agent.daily_checkin_required === false) { console.log(`🌊 事件触发型Agent ${agentId} (${agent.name}) 已确认身份,允许通行`); - } else { + } else if (agent.daily_checkin_required === true) { console.log(`🌊 定时型Agent ${agentId} (${agent.name}) 已确认身份,允许通行并登记签到`); + } else { + console.log(`🌊 Agent ${agentId} (${agent.name}) 已确认身份,允许通行(签到状态未标记)`); } return { allowed: true, agent: agent };