Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions external_plugins/glm-routing-suite/.zcode-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "glm-routing-suite",
"version": "0.5.0",
"description": "Four-stage workflow + delivery gate + graded task protocol with a soft stage gate and variant presets, ported from dsh-routing-suite (MIT/Apache-2.0): default zero-injection, completion-signal advancement, delivery_check evidence manifest, two-tier spec gating with red-team gates, PreToolUse write/edit gating, spec/react style presets",
"description_i18n": {
"en": "Four-stage workflow + delivery gate + graded task protocol with a soft stage gate and variant presets, ported from dsh-routing-suite (MIT/Apache-2.0): default zero-injection, completion-signal advancement, delivery_check evidence manifest, two-tier spec gating with red-team gates, PreToolUse write/edit gating, spec/react style presets",
"zh-CN": "移植自 dsh-routing-suite 的四阶段工作流+交付门禁+分级任务协议+软阶段门禁+变体预设:默认零注入、完成信号晋级、delivery_check 证据清单、两级规格门控含红队门、规格阶段 PreToolUse 扣住写入、spec/react 风格档"
},
"author": {
"name": "forrestneo"
},
"skills": "./skills",
"hooks": "./hooks/hooks.json"
}
40 changes: 40 additions & 0 deletions external_plugins/glm-routing-suite/NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
glm-routing-suite — a ZCode plugin port of dsh-routing-suite
Copyright (c) 2026 forrestneo (port). MIT License for this port's original
code. Upstream component licenses differ and are respected per component:

- preset/router-standard (router-core.mjs, router-bootstrap-v34.mjs):
yjh051108/dsh-routing-suite — https://github.com/yjh051108/dsh-routing-suite
Copyright (c) 2026 yjh051108. MIT License.

- graded/ (dsh-graded-mode): Copyright (c) 2026 the dsh-graded-mode authors.
Apache-2.0 License (see upstream graded/LICENSE). Any future port of the
graded two-tier task protocol carries Apache-2.0 attribution and
reproduces only its behavioral semantics, not its source.

Ported components:
- scripts/router_core.py ← preset/router-standard/router-core.mjs
(task-classification regexes, behavior bands, personas, complexity
heuristic, mode parsing — preserved verbatim where they are the measured
artifacts of the upstream P1-P23 experiments)
- scripts/delivery_check.py ← the deliveryCheck gate in
preset/router-standard/router-bootstrap-v34.mjs (v1.23-v1.28 semantics:
file/utf8 checks + 8-kind evidence manifest, reviewed visuals,
non-blocking numeric hint), re-exposed as a CLI
- skills/mode-router/SKILL.md ← the v1.20 four-stage progressive workflow
(understanding→planning→development→verification, completion-signal
advancement, STAGE_GUIDES behavioral guidance) as a protocol

Note on design lineage: v1.20 (read in full from router-bootstrap-v34.mjs)
fixes the persona to a single RL sentence and enforces behavior via staged
tool disclosure; the older band-swapped-persona design lives on only as
informational mode output. This port follows the v1.20 mainline.

Not ported (DSH-runtime specific, no ZCode equivalent):
- injector/ (runtime agent-loop injection, dev_* tooling, restrict)
- phase_begin/phase_advance/tools_catalog secondary disclosure plumbing
- graded/ (separate two-tier task-protocol plugin)

Measured claims (three behavior bands, weak-persona optima per model,
completion-signal advancement, anchor effects) originate from the upstream
repository's P1-P23 experiments on DeepSeek models and are cited, not
re-verified here.
64 changes: 64 additions & 0 deletions external_plugins/glm-routing-suite/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# glm-routing-suite: four-stage workflow + delivery gate (ZCode port)

Ported from the **measured mainline design** of router-standard v1.20 in [yjh051108/dsh-routing-suite](https://github.com/yjh051108/dsh-routing-suite) (MIT, 7k stars). Direction corrected after reading all 1293 lines of the upstream bootstrap: the value of v1.20 is not "swap personas per task" (the old design was dropped; the persona is a fixed single sentence) — it lives in two things:

1. **A four-stage progressive workflow**: understanding/alignment → planning → development → verification. Advancement is driven by completion signals (clarification / recorded plan / passing self-check / delivery check); **tool usage alone never skips a stage**. Upstream enforces this with hard tool restriction; ZCode plugins cannot, so it works here as protocol discipline plus reminders.
2. **A delivery_check evidence gate**: a mandatory local check before declaring done — file exists / non-empty / UTF-8, plus an evidence manifest (8 kinds; visuals must be `reviewed:true`; page deliverables need at least one reviewed visual; numeric invariants turn "I think it works" into "I verified it"). **This part is a complete port — pure local file validation.**

## Components

| Component | Role |
|---|---|
| `skills/mode-router` | The four-stage protocol: per-stage behavioral guidance (decide whether to ask by impact, attention reclamation, local-optima avoidance, hypothesis audit) + delivery gate usage |
| `scripts/delivery_check.py` | Delivery gate CLI: `--file <artifact> [--url <page>] --evidence evidence.json`; FAIL exits 1 |
| `scripts/router_core.py` / `route.py` | Regex task classification (build/fix/weak) — auxiliary info for reporting and stage emphasis |
| `hooks/on_prompt.py` | UserPromptSubmit hook: task echo + one-line stage-discipline reminder, fail-open |

## Quick start

```bash
# classify a task
python scripts/route.py --text "fix the login error" # → fix (stage-0 diagnosis is the focus)

# run the gate before declaring done
python scripts/delivery_check.py --file dist/app.py --evidence evidence.json
```

Example evidence.json:

```json
{"items": [
{"label": "main script", "kind": "file", "target": "dist/app.py"},
{"label": "smoke run", "kind": "run", "result": "python dist/app.py --selftest → 3/3 passed"},
{"label": "symbol count", "kind": "numeric", "result": "42"}
]}
```

## Measured-claims labeling

- **Upstream numbers** (three behavior bands, completion-signal advancement, anchor effects, 0%→100% completion): from the P1-P23 experiments of dsh-routing-suite on **DSH + DeepSeek models** (mostly n=2); **not reproduced in this port** — cited as design rationale only
- **This plugin's own tests** (2026-10-14, GLM-5.3): 34 exhaustive state-machine unit tests + 13 gate tests all pass; plus an n=20 ambiguous-task first-action A/B (10 tasks × 2 conditions × 2 reps, test/alignment-ab-results.json) — **no aggregate effect observed** (both conditions ask-first at 50%; the bare GLM-5.3 baseline is already high, a ceiling effect). The protocol's alignment benefit on GLM is **unverified** and is not claimed as a selling point

## Differences from the original (honest notes)

- Upstream enforces **hard** per-stage tool restriction via a DSH runtime injector and keeps a persistent stage section in the system prompt; ZCode plugins cannot do either, so this port relies on protocol discipline + hook reminders and model compliance
- `phase_begin` / `phase_advance` / `tools_catalog` (secondary disclosure) / goal tools / stages.json persistence are DSH tool-system specific and not ported
- `delivery_check` semantics are fully ported (v1.23-v1.28: the gate validates evidence instead of running its own browser; reviewed visuals; non-blocking numeric hint), only the interaction changes from tool call to CLI call
- Measured behavioral claims are cited from the upstream experiments on DeepSeek models, not re-verified on ZCode/GLM
- Stage state is not persisted; it lives in conversation context

## Side effects and dependencies

- **Network access: none.** Everything is local.
- **Command execution:** `python scripts/route.py`, `python scripts/delivery_check.py` (stdlib only).
- **File writes: none.** Scripts only read files and write stdout (delivery_check expresses PASS/FAIL via exit code 0/1).
- **Hooks:** one UserPromptSubmit hook, fail-open, disable via Settings → Plugins if unwanted.
- **No MCP server, no credentials, no data collection.**

## Install

Local test marketplace: Plugin Marketplace → Add → paste `C:\Users\w\Documents\z_fa\plugins` → Personal → dev-z-fa-e3f2b3e7 → glm-routing-suite → Install.

## License

MIT. Porting relationship and upstream attribution in [NOTICE](./NOTICE).
64 changes: 64 additions & 0 deletions external_plugins/glm-routing-suite/README_CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# glm-routing-suite:四阶段工作流 + 交付门禁(ZCode 移植版)

复刻自 [yjh051108/dsh-routing-suite](https://github.com/yjh051108/dsh-routing-suite)(MIT,7k★)router-standard v1.20 的**实测主线设计**。读完上游 1293 行 bootstrap 源码后修正过方向:v1.20 的价值不在"按任务换 persona"(老设计已弃用,persona 固定为一句 RL 句),而在两件事——

1. **四阶段渐进工作流**:了解/对齐 → 拟合方案 → 开发 → 验证。完成信号驱动晋级(澄清/计划/自检/交付检查),**工具使用本身绝不跳级**。上游用工具 restrict 强制执行;ZCode 做不到硬限制,以协议+提醒形式生效。
2. **delivery_check 交付证据门禁**:宣告完成前必须过的本地校验——文件存在/非空/UTF-8 三查 + 证据清单(8 种 kind,视觉类必须 `reviewed:true`,页面交付物必须有已复核的视觉证据,数值不变量把"我认为对"变成"我验证过")。**这部分是完整移植,纯本地文件校验。**

## 组件

| 组件 | 作用 |
|---|---|
| `skills/mode-router` | 四阶段协议:各阶段行为要点(歧义按影响决定问不问、注意力回收、防局部最优、假设审计)+ 交付门禁用法 |
| `scripts/delivery_check.py` | 交付门禁 CLI:`--file <交付物> [--url <页面>] --evidence evidence.json`,FAIL 退出码 1 |
| `scripts/router_core.py` / `route.py` | 任务正则分类(build/fix/weak)——辅助信息,用于报告任务性质和阶段侧重 |
| `hooks/on_prompt.py` | UserPromptSubmit 钩子:任务回显 + 一行阶段纪律提醒,fail-open |

## 快速上手

```bash
# 分类一个任务
python scripts/route.py --text "帮我修一下登录报错" # → fix(阶段0排查是重心)

# 交付前过门禁(模型在宣告完成前必须跑)
python scripts/delivery_check.py --file dist/app.py --evidence evidence.json
```

evidence.json 示例:

```json
{"items": [
{"label": "主脚本", "kind": "file", "target": "dist/app.py"},
{"label": "冒烟运行", "kind": "run", "result": "python dist/app.py --selftest → 3/3 passed"},
{"label": "语法计数", "kind": "numeric", "result": "42"}
]}
```

## 实测声明(分级标注)

- **上游数字**(三行为带、完成信号晋级、锚点效果、0%→100% 完成率等):来自 dsh-routing-suite 在 **DSH + DeepSeek 模型**上的 P1-P23 实验(多为 n=2),**未在本移植复现**,仅作设计依据引用
- **本插件自测**(2026-10-14,GLM-5.3):状态机 34 项穷举单测 + 门禁 13 项单测全过;另做了 n=20 的歧义任务首动作开/关对照(10 任务 × 2 条件 × 2 重复,test/alignment-ab-results.json)——**未观察到聚合效应**(两条件先问率均为 50%;GLM-5.3 裸基线已较高,存在天花板效应)。协议对 GLM 的对齐收益目前是**未证实状态**,不作为卖点宣称

## 与原版的差异(诚实声明)

- 上游用 DSH 运行时注入器做**硬**工具限制(每阶段只见本阶段工具)和 system prompt 常驻阶段声明;ZCode 插件无此能力,本移植以**协议纪律 + 钩子提醒**形式生效,依赖模型遵循
- 上游 `phase_begin`/`phase_advance`/`tools_catalog`(二级披露)/goal 工具/stages.json 持久化均为 DSH 工具系统专属,未移植
- `delivery_check` 语义完整移植(v1.23-v1.28:门禁验证据不自跑浏览器、reviewed 视觉、numeric 非阻断提示),仅交互从"工具调用"变为"CLI 调用"
- 实测数字(完成信号晋级、注意力回收等行为效应)引自上游在 DeepSeek 模型上的实验,未在 ZCode/GLM 复测
- 阶段状态不持久化,按会话上下文维持

## 副作用与依赖声明

- **网络访问:无。** 全部本地。
- **命令执行:** `python scripts/route.py`、`python scripts/delivery_check.py`(仅标准库)。
- **文件写入:无。** 所有脚本只读文件、只写 stdout(delivery_check 退出码 0/1 表达 PASS/FAIL)。
- **钩子:** UserPromptSubmit 一个,fail-open,可在 设置 → 插件 禁用。
- **无 MCP server、无凭据、无数据收集。**

## 安装

本地测试市场:插件市场 → 添加 → 粘贴 `C:\Users\w\Documents\z_fa\plugins` → 个人 → dev-z-fa-e3f2b3e7 → glm-routing-suite → 安装。

## 许可

MIT。移植关系与上游致谢见 [NOTICE](./NOTICE)。
129 changes: 129 additions & 0 deletions external_plugins/glm-routing-suite/hooks/gate_hook.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#!/usr/bin/env python3
"""PreToolUse 软门禁(P2):分级协议的规格阶段拦截 write/edit + 状态文件自保护。

协议(与 ZCode/Mimosa 实证格式一致):
允许 → 退出 0,无输出
拦截 → 退出 0 + stdout JSON:
{"hookSpecificOutput": {"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "..."}}

门禁语义(九评审修订版):
1. 自保护(分级/提醒激活时):Write/Edit/MultiEdit 指向 ~/.glm-routing-suite/ 状态文件
一律拒——状态仅 CLI 进程可写,防提示注入篡改门禁(安全评审 #b)
2. 阶段门(仅 graded 会话激活且 stage ∈ {brainstorm, l1-edit, l2-edit, review}):
拦 write/edit,理由附解锁命令
3. 降级:连续拦 3 次(10 分钟窗口内)自动降级为警告放行,防误伤卡死(架构评审)
4. fail-open:任何异常/超时/解析失败 → 静默放行(与 Mimosa 的 fail-closed 相反,
本门禁是纪律工具不是安全边界,宁可放过不可卡死)

手动冒烟:
printf '%s' '{"tool_name":"Write","tool_input":{"file_path":"C:/x/y.txt"}}' | python hooks/gate_hook.py
"""
import json
import os
import sys
import time
from datetime import datetime

_HOOK_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, os.path.join(_HOOK_DIR, os.pardir, "scripts"))

STATE_DIR = os.path.realpath(os.path.join(os.path.expanduser("~"), ".glm-routing-suite"))
GATE_BLOCK_LIMIT = 3
GATE_WINDOW_S = 600

PRE_DEV_STAGES = ("brainstorm", "l1-edit", "l2-edit", "review")
GATED_TOOLS = {"Edit", "Write", "MultiEdit"}


def _deny(reason):
print(json.dumps({"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": reason,
}}, ensure_ascii=False))
sys.exit(0)


def _safe_path_in_state_dir(path):
try:
p = os.path.realpath(path)
return os.path.commonpath([STATE_DIR, p]) == STATE_DIR
except (OSError, ValueError):
return False


def _load_gate_counter():
try:
with open(os.path.join(STATE_DIR, "gate.json"), encoding="utf-8") as f:
d = json.load(f)
if isinstance(d, dict) and time.time() - float(d.get("at", 0)) < GATE_WINDOW_S:
return int(d.get("blocks", 0))
except (OSError, ValueError, TypeError):
pass
return 0


def _save_gate_counter(n):
try:
os.makedirs(STATE_DIR, exist_ok=True)
tmp = os.path.join(STATE_DIR, "gate-%d.tmp" % int(time.time() * 1000))
with open(tmp, "w", encoding="utf-8") as f:
json.dump({"blocks": n, "at": time.time()}, f)
os.replace(tmp, os.path.join(STATE_DIR, "gate.json"))
except OSError:
pass


def main():
try:
try:
sys.stdout.reconfigure(encoding="utf-8")
except Exception:
pass
raw = sys.stdin.read()
data = json.loads(raw) if raw.strip() else {}
tool = str(data.get("tool_name") or data.get("toolName") or "")
if tool not in GATED_TOOLS:
return # matcher 已过滤,双保险

file_path = str((data.get("tool_input") or data.get("toolInput") or {})
.get("file_path") or "")

import suite_mode as sm
import graded as gr

mode = sm.load_state().get("mode", "off")
gstate = gr.load_state()
graded_active = gstate.get("stage") not in (None, "off")

# 1) 自保护:状态文件仅 CLI 可写(mode 激活或 graded 会话存在时)
if (mode != "off" or graded_active) and file_path and _safe_path_in_state_dir(file_path):
_deny("[glm-routing-suite] 状态文件仅 CLI 进程可写(防篡改门禁):请用 "
"suite_mode.py / graded.py 子命令操作状态,不要直接编辑 %s" % file_path)

# 2) 阶段门:分级会话的规格阶段扣住 write/edit
if graded_active and gstate["stage"] in PRE_DEV_STAGES:
blocks = _load_gate_counter()
if blocks >= GATE_BLOCK_LIMIT:
_save_gate_counter(0) # 降级后重置
sys.stderr.write("[glm-routing-suite] 门禁已连续拦 %d 次,自动降级为警告放行"
"(防误伤)\n" % blocks)
return
_save_gate_counter(blocks + 1)
_deny("[glm-routing-suite·graded] 阶段=%s:规格未审核通过,write/edit 暂扣。"
"解锁:完成规格后跑 `python graded.py review --decision approve`;"
"或 `python graded.py off` 退出分级模式" % gstate["stage"])

# 通过(develop/final 或未激活)→ 重置计数
_save_gate_counter(0)
except SystemExit:
raise
except Exception:
pass # fail-open
sys.exit(0)


if __name__ == "__main__":
main()
36 changes: 36 additions & 0 deletions external_plugins/glm-routing-suite/hooks/hooks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"description": "glm-routing-suite hooks: per-prompt close-range guidance (opt-in) + graded stage gate.",
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "process",
"command": "python",
"args": [
"${ZCODE_PLUGIN_ROOT}/hooks/on_prompt.py"
],
"timeoutMs": 4000,
"statusMessage": "glm-routing-suite: classifying task…"
}
]
}
],
"PreToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{
"type": "process",
"command": "python",
"args": [
"${ZCODE_PLUGIN_ROOT}/hooks/gate_hook.py"
],
"timeoutMs": 5000,
"statusMessage": "glm-routing-suite: 检查阶段门禁…"
}
]
}
]
}
}
Loading