ECC PR 队列治理实战:以 continuous-learning-v2 五层自循环守卫的合并审查为例解析 triage 决策链路
本指南以 ECC 仓库在 2026-03-13 记录的一份实时 PR 队列治理快照(docs/PR-QUEUE-TRIAGE-2026-03-13.md)为主体,完整还原"紧急 hotfix 追溯审查 → 开放队列逐项评估 → 归并性分桶 → 排序放行"的标准流程,并对照当前仓库源码逐层拆解被审查的 5 层自动会话守卫实现。读完你既能掌握一套可复用的 gh 驱动的 PR triage 方法论,也能理解 ECC observe 钩子如何避免自我观察(self-loop)这一典型自动化陷阱。
快照信息与 triage 数据来源
该文档是 everything-claude-code 拉取请求队列在 2026-03-13T08:33:31Z 的一份实时治理快照(Snapshot),其作用是把散落在各 PR 页面的状态收敛成一份"此刻队列健康度"报告。它使用四条数据来源,全部基于 GitHub CLI 的只读查询:
gh pr view:获取 PR 的 draft 状态、可合并性与基础描述;gh pr checks:读取可见的 CI / Bot 检查结果;gh pr diff --name-only:只看变更文件清单,快速评估影响面;- 针对合并头(merged head)的本地定向验证:
#399合并后,作者对 merge commit 指向的代码做本地核对。
本次扫描使用的"陈旧(stale)"判定阈值是:last updated before 2026-02-11,即截至 2026-03-13 超过 30 天未更新的 PR 视为陈旧。这份阈值定义是队列治理中关键的量化规则——没有它,"该先看哪个 PR"就会退化成主观偏好。
PR #399 追溯审查:一次紧急 loop-stop 修复的完整复盘
队列治理往往从"已合并 PR 的追认审查"开始,因为最近一次合并决定的质量直接决定后续队列评估的置信度。
基本信息与变更范围
- PR:
#399—fix(observe): 5-layer automated session guard to prevent self-loop observations - 状态:
MERGED,合并时间2026-03-13T06:40:03Z,合并提交c52a28ace9e7e84c00309fc7b629955dfc46ecf9 - 变更文件(2 个,均为 Shell 脚本):
问题背景:为什么需要"自动会话守卫"
ECC 的连续学习(continuous-learning-v2)机制中,observe.sh 作为 Claude Code 的 PreToolUse/PostToolUse 钩子在每一次工具调用时被触发,把调用记录写入 observations.jsonl;而 observer-loop.sh 是一个后台常驻循环,它会在观测数据累积到阈值后,再以 claude --print 非交互模式启动一个"分析会话"来归纳 instinct 文件。
问题由此产生:分析会话本身也是"工具调用",也会触发 observe 钩子;若钩子不区分调用方是人类还是自动化代理,就会形成 ECC 观察自己 Haiku observer 会话的自我观察死循环(self-loop),并污染其他工具的自动化会话元数据。这正是 #399 要消灭的核心缺陷。
五层守卫在源码中的逐层落位
对照当前仓库 observe.sh,可以确认这套守卫矩阵按顺序真实存在,且被刻意放置于项目检测逻辑之前——文件内注释明确警告:"keep these guards above detect-project.sh,因为 source detect-project.sh 会创建项目作用域目录并更新 projects.json,自动化会话必须在此之前返回"。五层依次为:
| 层 | 触发变量 / 载荷 | 语义 | 源码位置 |
|---|---|---|---|
| Layer 1 | CLAUDE_CODE_ENTRYPOINT |
仅允许 cli、sdk-ts、claude-desktop、claude-vscode 四种交互式入口继续;其余入口一律 exit 0 |
observe.sh |
| Layer 2 | ECC_HOOK_PROFILE=minimal |
minimal 钩子配置档案抑制非必要钩子 | observe.sh |
| Layer 3 | ECC_SKIP_OBSERVE=1 |
自动化会话主动"合作式跳过"环境变量 | observe.sh |
| Layer 4 | stdin JSON 中的 agent_id |
子代理(subagent)会话天然属于自动化,只要载荷携带 agent_id 即退出 |
observe.sh |
| Layer 5 | ECC_OBSERVE_SKIP_PATHS |
已知 observer 会话路径排除,默认排除 observer-sessions,.claude-mem,对 STDIN_CWD 做子串匹配 |
observe.sh |
需要特别说明的是 Layer 1 的处理策略:文档审查结论称之为 fail-closed(失败即关闭)形状——即无法确认是人类会话时默认不放行。注意与实现细节的一致性:sdk-ts 之所以在白名单中,是因为 Agent SDK 会话仍可能由人类经 Happy 等界面交互驱动,非交互的 SDK 自动化则交由 Layer 2–5 继续过滤(见 observe.sh 的注释)。
而作为呼应,observer-loop.sh 在启动分析子进程时显式设置 ECC_SKIP_OBSERVE=1 ECC_HOOK_PROFILE=minimal,即自动化分析端主动配合 Layer 2 与 Layer 3 完成闭环。
验证手段与测试矩阵
文档记录了对合并头 546628182200c16cc222b97673ddd79e942eacce 的四类验证:
- 语法检查:对两个变更后的 Shell 脚本执行
bash -n; - 全量钩子测试:运行
node tests/hooks/hooks.test.js,结果为204passed、0failed; - 定向钩子调用(targeted hook invocations),覆盖六类场景:
- 交互式 CLI 会话(默认放行路径);
CLAUDE_CODE_ENTRYPOINT=mcp(应被 Layer 1 拦截);ECC_HOOK_PROFILE=minimal(应被 Layer 2 拦截);ECC_SKIP_OBSERVE=1(应被 Layer 3 拦截);- 携带
agent_id载荷(应被 Layer 4 拦截); - 裁剪后的
ECC_OBSERVE_SKIP_PATHS(验证 Layer 5 匹配逻辑)。
可以印证的是,仓库测试目录中确实沉淀了针对这套守卫的回归测试,例如 tests/hooks/observe-entrypoint-allowlist.test.js 专门钉住 Layer 1 的 entrypoint 白名单(其头部注释还记录了更早的 #2102 修复:当时白名单缺 claude-vscode,导致 VS Code 扩展用户观察记录静默丢失)。
行为结果(Behavioral result) 三条:核心 self-loop 修复生效;自动化会话守卫分支按预期抑制了观察写入;最终的 non-cli => exit 入口逻辑是正确的 fail-closed 形态。
遗留发现与 verdict
审查没有止步于"能跑",而是给出了两条分层级的遗留发现:
- Medium 级:被跳过的自动化会话在守卫退出前仍会创建 homunculus 项目状态。原因在于 observe.sh 在到达守卫块之前就已经解析
cwd并准备项目检测(从 stdin JSON 提取cwd并尝试git rev-parse --show-toplevel),而真正 source 的 detect-project.sh 会在 L104/L142 与 L232-L256 处mkdir -p创建projects/<id>/...目录并更新projects.json注册表——即使该会话随后因守卫而提前exit 0。换言之,守卫拦截了写入,却拦不住先行的项目注册副作用。 - Low 级:新守卫矩阵没有随 PR 携带直接回归覆盖。钩子测试套件验证了相邻行为,但未直接断言
CLAUDE_CODE_ENTRYPOINT、ECC_HOOK_PROFILE、ECC_SKIP_OBSERVE、agent_id、裁剪 skip-path 这些新分支。
最终结论(Verdict):就首要目标(紧急 loop-stop 修复)而言 #399 技术上正确、可安全合并;但仍需一个 follow-up issue 或补丁,把自动化会话守卫前移到项目注册副作用之前,并为守卫路径补充显式测试。
这一"合并通过 + 遗留项跟进"的双轨结论,正是把一次紧急修复从"堵住症状"推向"根因收敛"的关键动作。
开放队列盘点:4 个待办 PR 的实时快照
快照时刻开放队列共有 4 个 PR,无任何 PR 触发 >30 days 陈旧规则。原始队列表完整如下:
| PR | Title | Draft | Mergeable | Merge State | Updated | Stale | Current Verdict |
|---|---|---|---|---|---|---|---|
#292 |
chore(config): governance and config foundation (PR #272 split 1/6) |
false |
MERGEABLE |
UNSTABLE |
2026-03-13T07:26:55Z |
No |
Best current merge candidate |
#298 |
feat(agents,skills,rules): add Rust, Java, mobile, DevOps, and performance content |
false |
CONFLICTING |
DIRTY |
2026-03-11T04:29:07Z |
No |
Needs changes before review can finish |
#336 |
Customisation for Codex CLI - Features from Claude Code and OpenCode |
true |
MERGEABLE |
UNSTABLE |
2026-03-13T07:26:12Z |
No |
Needs manual review and draft exit |
#420 |
feat: add laravel skills |
true |
MERGEABLE |
UNSTABLE |
2026-03-12T22:57:36Z |
No |
Low-risk draft, review after draft exit |
值得先读懂表中三个 GitHub 状态字段的判别价值,这是后续分桶判断的事实基础:
- Mergeable(分支级可合并性)区分
MERGEABLE/CONFLICTING:冲突的 PR 连进入 review 的资格都没有,必须先行 rebase; - Merge State 区分
UNSTABLE/DIRTY:UNSTABLE表示分支本身可合并但 CI 尚未通过或被变更,DIRTY则意味着存在冲突或未提交变更; - Draft 标志表达"作者认为尚未就绪"的意图信号,draft PR 不应被当作合并候选严肃对待。
逐 PR 评估:决策依据怎么摆
#292 — Governance / Config 基础(非 draft,MERGEABLE / UNSTABLE)
变更范围覆盖仓库根目录的治理与配置地基:.env.example、.github/ISSUE_TEMPLATE/copilot-task.md、.github/PULL_REQUEST_TEMPLATE.md、.gitignore、.markdownlint.json、.tool-versions、VERSION(其中 .env.example、.markdownlint.json、.tool-versions、VERSION 在仓库根目录当前均真实存在)。
可见检查:CodeRabbit 与 GitGuardian Security Checks 均通过。评估要点:
- 当前队列中最干净的合并候选;分支已刷新到最新
main; - 可见的机器人反馈属于 minor/nit 级别,不构成明显的合并阻塞;
- 主要保留意见:当前只能看到外部 Bot 检查,
gh pr checks输出里没有出现 GitHub Actions matrix 运行。
结论:Mergeable after one final owner pass——保守路径是先由人工快速过一遍 .env.example、PR 模板与 .tool-versions 的 nit 项再合并。
#298 — 大规模跨域内容扩展(非 draft,CONFLICTING / DIRTY)
范围:35 个文件,横跨 Java、Rust、移动端、DevOps、性能、数据与 MLOps 的文档及 skill/rule 扩充(当前仓库中的 rules/java、rules/rust、rules/react-native 等目录即属于这类领域内容的地基)。
可见检查:CodeRabbit、GitGuardian Security Checks、cubic · AI code reviewer 均通过。但评估结论依然是否定的,原因有三层:
- 与当前
main冲突,分支层面已不可合并; cubic在35个文件中识别出34个问题,且这些 findings 是实质性与技术性的(覆盖多个新 skill 中破损或误导的示例),不是纯风格清理;- 即便解决冲突,体量也决定了需要一次审慎的内容修正 pass,而不是快速合并决策。
结论:Needs changes。先 rebase 或重新叠层(restack),再解决示例质量缺陷;如果节奏重要,按领域拆分而不是扛一个超大型 PR。
#336 — Codex CLI 定制(draft,MERGEABLE / UNSTABLE)
提议修改的文件集中在 Codex 集成与全局 git 钩子路径,其文件路径在当前仓库中可一一对应:scripts/codex-git-hooks/pre-commit、scripts/codex-git-hooks/pre-push、scripts/codex/check-codex-global-state.sh、scripts/codex/install-global-git-hooks.sh、scripts/sync-ecc-to-codex.sh(见 scripts/codex-git-hooks 与 scripts/sync-ecc-to-codex.sh)。
评估要点:
- 已不再冲突,但仍是 draft 且没有经过有意义的 first-party review;
- 它改动的是用户全局 Codex 设置与 git-hook 安装行为,运行影响半径远超纯文档 PR;
- 可见检查只有外部 Bot,缺少完整 GitHub Actions run;
- 分支来自 contributor fork
main,在变更状态前应额外做一次内容 sanity pass。
结论:Needs changes before merge readiness——所需的不是已被证明的代码缺陷修复,而是流程/审查向要求:完成人工审查、运行或确认 global-state 脚本验证、审查完成后再退出 draft。
#420 — Laravel Skills(draft,MERGEABLE / UNSTABLE)
提议范围与当前仓库中 rules/php(patterns / security / testing)、skills/laravel-patterns/SKILL.md、skills/laravel-security/SKILL.md、skills/laravel-tdd/SKILL.md、skills/laravel-verification/SKILL.md、skills/configure-ecc/SKILL.md 与 examples/laravel-api-CLAUDE.md 这一组 Laravel 内容型资产对应。
评估要点:内容密集、运行风险低于 #336;但仍是 draft 且没有实质人工审查 pass;实时状态中没有任何指向合并阻塞器的信号——仅因仍是 draft 且审查不足,就不应合并。
结论:Review next after the highest-priority non-draft work——作者准备好退出 draft 后即可成为优质审查对象。
归并性分桶:把状态翻译成动作
文档用四个分桶把上述判断收敛为可执行动作,这是一种值得借鉴的输出形态——桶的粒度比单条结论更适合驱动下一步:
- 可立即合并或在 owner 最终审查后合并:
#292 - 合并前需要变更:
#298、#336 - Draft / 在任何合并决策前需要审查:
#420 - 陈旧(>30 天):无
推荐处理顺序与底线结论
推荐顺序(含理由):
#292:当前最干净的实时合并候选;#420:运行风险低,但需等待 draft 退出并完成真正 review pass;#336:谨慎审查,因为它改动全局 Codex 同步与钩子行为;#298:先 rebase 并修复实质内容问题,再投入更多 review 时间。
Bottom Line(每条一句话,方便回归):
#399:安全的 bugfix 合并,仍值得一次清理类 follow-up;#292:当前开放队列中最高优先级的合并候选;#298:不可合并——冲突加实质内容缺陷;#336:不再冲突,但 draft 且验证薄弱,未就绪;#420:draft、低风险内容通道,待非 draft 队列处理后再审查。
实时刷新(Live Refresh)与三小时后的队列漂移
快照在 2026-03-13T22:11:40Z 做了一次刷新(距首版约 13.5 小时),这是队列治理中"快照不设最终版"思想的体现:合并状态会漂移,结论需跟随更新。
主分支:origin/main 目前全绿(含 Windows 测试矩阵),主线 CI 修复不是当前瓶颈。
刷新后的队列读数:
#292仍是最可行动的 PR(Next actionable PR),最高信号剩余工作是合并前对.env.example与 PR 模板对齐的小范围正确性 pass,而非 CI 修复;#420的可见检查发生变化:CodeRabbit因 PR 是 draft 而 skipped,GitGuardian Security Checks通过——注意观察这个细节:bot 检查本身也会随 draft 状态调整执行策略;#336明确被划入 manual-review lane, not immediate merge lane,因其触碰全局 Codex sync 与 git-hook 安装行为;#298仍是"最难的遗留 PR"(Last priority),必须先 rebase。
刷新后的最终顺序:#292 → #420 → #336 → #298(与首版推荐顺序一致,但理由随检查状态漂移被强化)。
方法论沉淀:如何复刻这套 triage 决策链路
复盘整份文档,可以提炼出四条不依赖具体 PR 的可迁移规则:
- 量化陈旧规则:为"何时该被优先处理"设置显式时间阈值(本仓库为 >30 天),避免队列管理退化为直觉;
- 分层判断状态字段:先看分支级
CONFLICTING/MERGEABLE,再看 merge stateDIRTY/UNSTABLE,再看 draft 意图信号,最后才进入内容评估——顺序错乱会导致把时间花在根本无法合并的 PR 上; - 审查必须分离"功能正确"与"回归覆盖":
#399的 verdict 同时包含"技术上正确可合并"与"缺守卫路径直测",二者不冲突,但后者必须显式记入 follow-up 而非随合并消解; - Bot 检查是信号不是结论:
CodeRabbit、GitGuardian、cubic的通过/跳过状态需要与"是否有人类 review pass、是否有 GitHub Actions matrix run"交叉验证——本快照中多个 PR 都只有外部 Bot 可见,这本身就是需要保留意见的信号。
如果要在本地复现这套只读核验流程,#399 一节已给出可直接照搬的命令序列:gh pr view、gh pr checks、gh pr diff --name-only 确认状态与影响面,再用 bash -n 与 node tests/hooks/hooks.test.js 完成本地验证,必要时配合 tests/hooks 目录下的定向回归测试(如 observe-entrypoint-allowlist.test.js)深入单条守卫路径。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00