Skip to content
Back to skills

Opencode

BSecurity

HopSpec turns a task into a structured spec (goal, steps, verification points) that the hopjit engine executes step by step — progress is on the books, checkpoints are enforced by the engine, and runs resume across sessions. This skill is the single entry point for four things: (1) complex tasks that need controllable, reliable execution (multi-step, progress worth keeping, needs verification, must resume after interruption) — upgrade them into a HopSpec run by the engine; one-line questions ...

  • 15 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 24, 2026
ai-agentspythongoshellbashnodegitapi

Works with

  • cli
  • api
  • mcp

Security analysis

B84/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 7 files and shows the line behind each finding

Scanned October 4, 2026

npx -y skills add hoplogic/hop3 --skill opencode --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Opencode?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Opencode
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/hoplogic-opencode-hop3/badge)](https://www.skillsdirectory.com/skills/hoplogic-opencode-hop3)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: hop
description: HopSpec turns a task into a structured spec (goal, steps, verification points) that the hopjit engine executes step by step — progress is on the books, checkpoints are enforced by the engine, and runs resume across sessions. This skill is the single entry point for four things: (1) complex tasks that need controllable, reliable execution (multi-step, progress worth keeping, needs verification, must resume after interruption) — upgrade them into a HopSpec run by the engine; one-line questions are answered directly and never pulled into hop. (2) Running an existing HopSpec file. (3) Building, translating, or revising HopSpec (translate a natural-language skill into a spec; fix a few spots in an existing spec). (4) Resume intent — "continue the task from last time", "where were we" — picks up the current task ledger. Only when the user explicitly asks for MCP/standalone does it run in standalone mode (the spec executes inside the hopjit server process with its own LLM; this session only starts it and answers intervention points).
user-invocable: true
---

%% @trace
	id: hopjit-opencode-driver-hop
	source: [[hop-skill]]
	source_id: hopjit-driver-hop
	type: adapt
	last_sync: 2026-10-03T14:13+0800
	note: /hop 的 opencode 载体适配(适配基准=Codex 版 driver/codex/hop-skill.md——作者抓"在 codex /hop 都能用,为什么在 opencode 不装?"撤销上一批"v1 不装"裁定后补装;同语义分载体不许步骤语义漂移)。载体差异三处:触发=隐式(opencode 按 description 触发,用户说 hop/继续上次的活即中)/问人=question 内置工具(opencode-driver-carrier 映射表)/外包与阅卷按 subagent 能力降级(无 subagent 全自驱+判据硬化,零仪式——opencode 有内置 general subagent,常态可外移)。布局契约 [[opencode-driver-carrier#^anc-driver-opencode-install-layout]]。演进随 CC 版同批,归 git log。
%%

# hop — 日常把活交给引擎管(opencode 载体)

把你正要干的活(或对话里已经列出的 plan)升格为一份 HopSpec 跑起来。**你自己驱动、自己干活**——引擎只管三件事:**顺序不乱、把关不跳、进展有账**(对话断了活不死,回来接着跑)。

hop 是用户唯一看得见的入口——跑成品 spec、构建/翻译/修订 spec、走 MCP 独立模式,都从这里分派出去(见下「0. 分派」);本篇正文讲的是主路:**现场的日常活**升格为任务卡——核心是**计划可控、执行可靠**(进 hop 的活恒享建卡+进展账+把关全套)。主路恒复用模式——不探测 MCP、不做参数仪式;执行缺省在当前会话(活是当前会话的活,上下文就在这里),例外规则见下"步骤的注意力管理"。

## 用法(七动作:开 / 列 / 切 / 改 / 归档 / 提纯 / 决策)

```
hop 查一下X的三个来源,写成报告发给我   ← 开新活(说"hop"或直接描述要管护的活)
hop                                  ← 有当前活:续跑;没有:列清单
hop list                             ← 手头活清单(各到哪步、停在哪)
hop 2  或  hop 合同                   ← 切到那个活,接着干
hop archive 2                        ← 归档(不要了/干完收起;不删,历史全留)
hop distill 2                        ← 提纯(把干完的活总结成可复用的成品 spec)
hop 决策                              ← 把挂着的待拍决策点逐个说清楚请人拍板,拍板过程存档
```

hop 是**独立的 plan/执行工具**:多个活并存、随开随切——像 todo 管理器,但每个活是一份可控可靠的 spec:有账、可执行、可续跑、有把关。

## 前置:CLI 定位

首次动作前按 `command -v hopjit` 定位一次 CLI,命中固化为 `<CLI>` 前缀(完整调用前缀,可能是 hopjit 或 node 绝对路径,文中恒写 `<CLI> <command>`);不中直接报错请用户装好(`npm i -g @hoplogic/hopjit`)重试,不翻目录找替代。

## 执行流程

### 0. 分派:用户给的是什么,走哪条路

hop 是唯一入口,进来先判用户给的是什么,五条路:

**进分派之前先补一件安装期做不了的事(2026-10-03 作者定"只敲 npm install,其他都让 /hop 解决")**:skill 是 npm 装包时自动装上的。opencode 的 MCP 注册在用户级 opencode 配置(`~/.config/opencode/opencode.jsonc`),装包时已写好,本项目不需要再补什么;但若 `hopjit` 命令能找到而 配置里没有 `mcp.hopjit`(用户装包时跳过了钩子,或配置文件是后来才建的),跑一次 `hopjit install-skill --carrier opencode`(幂等)补上,再告诉用户一句。已经有的就什么都不做。

- **一句话能答完、不需要留痕的**(算个数、翻译一段)→ 直接答,不进 hop。hop 不劫持对话。
- **复杂的、需要可控可靠保障的活**(多步骤、要进度记录、要独立核验、中断后要能接着干)→ 下面第 1 节起的升格流程:建任务卡、引擎管进度与把关。这是 hop 的主路。
- **一份现成的 HopSpec 文件**(用户给了路径,或指名跑某个提纯件 / 示例)→ 不升格,直接按 `hopspec` skill 的协议跑(同目录下的 `hopspec/SKILL.md`,模型可调、用户菜单不显示):参数确认、介入点问人、终态按契约呈现。`hop list` 不列它——它不是"手头的活"。
- **构建 / 翻译 / 修订 HopSpec**:把自然语言 skill 翻成 spec → 按 `hopbuild` skill;改一份已有 spec 的几处 → 按 `hopfix` skill。`hopbuild2` 是实验件,只在用户点名"hopbuild2"时用,不自动选。
- **用户明说"走 MCP / standalone"** → 按 `hopspec-mcp` skill 的协议跑:spec 在 hopjit server 进程里由它自己的 LLM 执行,本对话只做启动、介入点应答和结果呈现。

拿不准用户要的是哪条,问一句,不猜。

**运维场景的特殊规则按需读**:活涉及 ssh / 远端机器 / 多台环境,或项目 `hopjit.yaml` 里有 `environments:` 段,先读本目录 `references/hop-ops.md`(机器分级、按机器写已批准命令前缀、测试机整机放行)。其他活不用读它。

### 1. 升格:todo plan → spec(一个样例,不是一套规范)

**先分流,再消歧,先查有没有现成流程可复用,然后才从头升格**:

- **分流——这活该进 hop 吗**:进 hop 的活恒享全套(建卡+进展账+把关),判据是**要不要留进度记录、要不要中断后能接着干、要不要独立核验把关**。对话里一句话能答完、不需要留痕的("3+5 等于几""这段话翻译一下"),自然语言直接干,别建任务;拿不准就问用户一句。**没有"轻任务降配"——进来就是全套,嫌重说明它不该进来**;
- **消歧——关键输入缺失或目标多义时,先问清再建卡**:缺城市的天气查询先只问城市;"把刚才的机制简化"这类范围含混的话不许直接开任务——问清范围前不产生实例;
- **轻任务减编排不减把关**:简单活不必照抄下面样例的多段结构,但 **check 不减**——核验避免幻觉是应该的(一次性查询恰是幻觉面最大的场景,check 逼你对着产出如实判一次,是价值本体不是重量)。轻任务缺省形态 = 执行步 + check(如 `act free → check final`),不是裸单步;
- **查现成流程——从头写 spec 之前,先看有没有上次沉淀的流程可复用**(提纯的消费半边——只存不用等于白提纯):动手扫之前**先给用户一行提示**:"我先看看已有的任务流程里有没有可复用的——想跳过就说'直接开'"(这一步不静默做:用户看得见才知道你在干什么、才知道有跳过的口子)。然后扫 `hop_tasks/specs/` 各件的 `# Spec:` 标题与 Goal(一行一件,扫描很轻)。命中(同类或大体同类)→ 告诉用户"这类活有现成流程(上次<某活>提纯的),拿它当底稿开?"——同意即**以这份现成流程为底稿建一张新任务卡**(完全同类=照抄+填这次的参数,差一截=底稿上改;比从头写快且带着实战验证过的把关),照常走 hop 全套(建卡+进展账+把关)——**不直接跑提纯件本身**(直接跑=没任务卡、list 看不见、中断接不上;用户自己明说要用 hopspec skill 跑提纯件的从之);没有现成流程才从头写。**用户说"直接开"(或"别查了/从头来")→ 跳过本步径直建卡**(作者定 2026-08-28——用户比你清楚这活是不是新东西,明示直开就不拿清单打断;分流与消歧不随之跳)。**用户问"哪些可以复用/有什么现成的"** → 列 specs/ 清单(名字+Goal 一行一件),这也是查询动作,人问就答。`hop_tasks/specs/` 目录不存在就是还没提纯过任何活,静默跳过此步零仪式。

把任务(或你已列出的 plan)写成 spec。**粗没关系——后面还没想清楚的段落,写成 `[subtask free]` 到步展开**(引擎一等形态,作者定 2026-08-27:本质是到这步以后,做一个本步的 plan-do-check-retry-pass 展开):

```markdown
2. [subtask free] 后面的活(到步展开)
  - ← 前面的产出
  + → 交付物 % text  # 说明
```

底下**一个子步都不用写**。执行到这里引擎自己停下来向你要计划——响应是 `adaptive_needed` 且带 `reason: "initial_plan"`(**这不是失败**,别做失败归因),`expansion_context` 里是 ← 输入的**实际值**(拿真产出定计划,不是盲规划;null 值项见 `missing_inputs`——计划里安排取数或按缺失处理);你出子步骤提交(`--replan`,协议同"边跑边改计划"节),引擎接续执行;展开次数超上限时引擎拒收并在报文里给续批协议——**把情况原文呈给用户问"继续还是收手",用户批了才照报文指引重交,你无权替答**(预算是人给的,追加也须人批)——**展开计划本身不过阅卷**(出计划、提交的都是你,引擎两闸是把关方;恒外移的只有 check final 的判定,别把"阅卷外移"误解成一切计划都要外移)。两条展开纪律引擎强制:**展开物必须含 check**(运行时出的计划无人预审,check 是唯一把关);**展开物禁 commit**(不可逆动作必须写卡时显式声明——要 commit 写在 subtask free 外面消费其交付物)。中文写法 `[子任务 开放]`。样例:

```markdown
# Spec: 调研X并出报告
Id: hop-20260826-1
Goal: 查清 X 的现状,交叉核对后成文发出

## Outputs
- report % markdown  # 调研报告

## Steps
1. [act free] 查 X 的三个独立来源
  + → sources % yaml  # 来源与要点

2. [reason] 交叉核对,整理要点
  - ← sources
  + → digest % text  # 核对后的要点

3. [subtask] 成文并把关
  - ← digest
  + → report % markdown  # 调研报告
  3.1. [act free] 写初稿
    - ← digest
    + → report % markdown
  3.2. [check final] 核对:来源全覆盖、结论与要点一致
    - ← report
    + → ok % bool  # 判定
    + → note % text  # 缺口

4. [commit] 发出去
  - ← report
```

升格要点(就这几条,其余随意):

- 每行一个类型标:干活 `[act]` / 思考 `[reason]` / 机器或自查把关 `[check]` / 要问用户 `[ask]`/`[confirm]` / **不可逆动作(发送/删除/发布)必须 `[commit]`**——这是最容易标错的一个:凡是"做了就收不回"的都是 commit,不是 act;
- `[commit]` 前面必须站着 `[check final]` 或 `[confirm]`(引擎 P8 会拦,先懂为什么:授权完成才许不可逆);
- **改仓库正式文件的活,改动阶段进 worktree**(2026-08-30 作者抓实撞后立——修复步标 act free 直改共享工作区=把 commit 的事标成 act 混过把关,正是上一条最容易犯的形态):会写 src/docs/tests 这类要留下来的文件的步骤,在独立 worktree 里改+自测(`WT=<目录>; git worktree add "$WT" <基线>`——act"可逆"对改文件场景的物理兑现:主区物理未被碰、并行会话撞不了车、弃区即完全回滚);`[check final]` 对 worktree 里的成品验收;**合入主区+推送整体归 `[commit]` 步**(把关过了才把改动请出隔离区);弃区路径恒用建区时的同一变量不手打。只写 work_zone/临时区的活照旧,不加仪式;
- `[check]` 步的输出槽是**恰好一个 bool 型(判定)+ 一个 text 型(说明)**——槽位看的是类型不是名字,`ok`/`note` 是惯用名不是强制名(多 check 不撞名时用语义前缀);check 须在 subtask 内(顶层平铺是 C6 error);
- `[check final]` 是收尾把关——**它后面不能再有干活的步骤**(把关完只许 commit/exit,写计划时把关放段落末尾,探索性步骤都排它前面);
- **产出链完整**(P11/报告类常撞):每个步骤 `- ←` 引用的变量必须来自前序步骤 `+ →` 或 Inputs——凭空引用是 V1 error;交付物变量(Outputs 声明的)必须有某一步真的产出它,缺产出步是 P11 error;
- Goal 一句话 + Outputs 一个交付物(引擎兜底"做完=什么"的验收面);
- **带 body 的步骤,说明与 body 功能保持一致**(作者定 2026-08-30——说人话说完整):`>` 说明如实说清 body 在干什么,不许说明写"核对清单"而 body 里藏着别的动作。判据:只读说明的人对这步的预期与实际零偏差;
- **对话结晶必须落卡(充分供给,不吝啬 token——必做非可选)**:对话里已拍的板、定过的口径、排除项、材料指针,**全文写进任务卡的背景/参考节**。判据:新会话或子代理**读卡即接手,零追问**。语境不落卡,跨会话续跑只剩引擎的结构账;且阅卷子代理(见下"阅卷外移")的供给全靠卡——语境缺席它只能盲判;
- **写卡时列出 `## 已批准命令`**——这是任务卡的一个段,授权只对这张卡起的 run 有效;普通对话里跑命令与它无关,照旧走载体。把这个活要跑的命令前缀一行一条写进去(放 Config 之后、Steps 之前),之后这些命令经 hopjit 按卡放行,不再逐条过载体的权限弹窗。**清单管的是"这个任务允许跑什么",不管在哪一步跑**——同一条命令在 act 步骤里跑是探索(可重跑),在 `[commit]` 步骤里跑是提交(前面必须过 check final 或 confirm,才执行一次),探索态还是提交态由步骤类型定,引擎按态把关,不靠清单区分。commit 步骤要跑的命令也从这张清单来——写卡时把它写进 `[commit]` 的 hop_python body(`subprocess.run([...], cwd: ...)`),引擎执行到那一步时直接跑 body,不再临场调工具;body 里的命令不在清单上同样被拒。所以写卡时要同时想好两件事:清单列全,不可逆的那条放进 commit 的 body。前缀写到能区分意图的那一层:`- python3 scripts/ssh_exec.py --config configs/x.json` 放行所有以它开头的调用,`python3 evil.py` 不行;`- git status` 放行 `git status --short`,不放行 `git push`——要 push 就单独列 `- git push`,并把它放进 commit 步骤。首项不能是 hopjit。不必问用户要不要列——这是升格的一部分,用户在任务卡里能看到;
- **关键词语言随项目走**(2026-09-03 language 特性落地):写卡前看项目 `hopjit.yaml` 有没有 `language: zh`——有就用中文关键词写任务卡(`[探索 开放]`/`[检查 终检]`/`## 目标`,对照表在语法参考 §12),没有或写 en 就用英文。两种语言引擎恒等价,写"错"不报错,跟着项目缺省走是为了产物风格统一。**存量 spec 转语言用 `<CLI> lang <spec文件> --to zh|en`**——先自动备份(同目录 `.bak.时间戳` 文件)再原地改写,只动关键词不动变量名/说明/body,转换引病会拒绝写回。用户说"把这份 spec 转成中文关键词/转回英文"就是要这个命令。**用户要改项目语言缺省**("以后生成的都用中文关键词")→ 改 `hopjit.yaml` 的 `language:` 键值——这是给用户干活的正当配置修改,改完口头确认一句"项目语言缺省已改为中文,之后 hopbuild 生成物与树读回都是中文关键词";改之前该文件里没有 language 键就加一行,有就改值,别的键一个不碰;
- 上面几条覆盖高频实撞坑;更复杂的形态(loop/case/for-each/类型面/中文关键词)**用时读引擎包内语法参考全量**(`<npm root -g 输出>/@hoplogic/hopjit/docs/concepts/HopSpec V3语法参考.md`——随包分发,源码库内同路径)——别凭印象写复杂结构,validate 报错拿着代号对文档改。

任务卡落 **`hop_tasks/<任务名>/<任务名>.md`**(一任务一目录——任务的材料/草稿/证据全住自己目录里,归档挪一个目录全走,不纠结多文件同步;卡文件与目录**同名**而非固定名 `spec.md`——Obsidian 双链按文件名解析,同名制下 `[[<任务名>]]` 照常可链不撞车)。**起名自动**:从任务话语提炼语义名,语言与用户话语一致(中文任务中文名——HopSpec 的中文标识符是一等公民;不转写不翻译),撞名加日期后缀;`# Spec:` 标题即清单显示名。

**任务卡结构**——任务文件不是纯计划,是**计划+语境同体**的卡:spec 段落(Goal/Outputs/Steps——引擎读)之外,加叙事段落(人和 LLM 读,引擎无视,doc-ref 可引用进执行 prompt):

```markdown
## 背景            ← 为什么干这活、来源、对话里已拍的口径(开工时写,口径变更时更)
## 参考            ← 材料链接、相关卡、[[双链]](可省)
## 处置记录        ← 关键判断/口径变更/意外发现,逐条追加(行格式:
                     - YYYY-MM-DD <一句话>)——记"为什么",不记流水(流水在引擎账上)
```

**为什么**:跨会话续跑时执行状态引擎有账,但**语境**(为什么改版/口径是什么/上一段撞了什么)只活在对话里——对话没了语境就没了。卡式结构让新会话/复跑者读卡即接上;归档后计划+语境成对,固化提纯有完整原料。**背景/参考等内容章节引擎缺省全程供给执行 LLM**(写进卡=喂给引擎,不需要任何引用或标记——2026-08-27 作者定'写在 spec 文件的内容章节就是缺省要供给的内容';处置记录是惯例名单成员天然不进 prompt〔2026-08-29 A 案:标题免带标记;其它想留给人的节用 `(不供给)` 显式标〕)。**处置记录是给下一个读者写的**,不是日志。

两条纪律:**节序**——spec 段在前、叙事段在后、处置记录恒居文件末(追加恒尾部,机械安全不碰契约区);**计划镜像归引擎**——改计划(replan)后文件 Steps 节由引擎写回同步,你不手工改文件的 spec 段——写回落地前的过渡期,改完计划口头提醒用户"文件里的步骤节暂以引擎账为准"。

### 2. 自驱循环(你就是执行者)

**⚠️ 执行恒在当前会话——禁止调 `mcp__hopjit__start_run`,检测到 MCP 注册也不用,不管任务多大**(hopissues/0071 实撞立规 2026-09-04:driver 觉得"任务量大,交引擎自跑更高效"调了 start_run——引擎独立模式用裸 API 模型自跑,读两批原文即撞 1M 上下文墙,烧 6.2M tokens 后 retry 耗尽失败,最后还是回会话分批干完。教训:hop 的活是本会话的活,上下文在这里,效率判断不覆盖协议——`start_run` 是 MCP 独立模式的入口,永远不是 hop 的)。觉得任务太大想交引擎自跑?两条正路:在会话内分批做(大面积翻查外包 agent,见"步骤的注意力管理");或向用户明说建议改走 MCP 独立模式,用户点头才换轨。本节只用 `run`/`submit_and_fetch_next` 两条 CLI:

**卡上已批准的命令有两种执行方式,核的是同一张清单。** act 步骤里,agent 临场拼参数、调 `mcp__hopjit__run_approved_command` 执行——这是探索态,随时可重跑。`[commit]` 步骤里,命令写在 body 里(写卡时定死),引擎到这一步直接执行,agent 不调工具——这是提交态,引擎保证 check final 或 confirm 已经过了,执行一次。两态的区别在步骤类型,不在清单。本段讲前者的调用方式。它与上一条"禁 start_run"并列:走 MCP 的只是命令执行这一口,run 的驱动和推理仍在本会话。

调用形态(参数值的来源写死,不要猜):

```
mcp__hopjit__run_approved_command(
  state_dir   = run 响应里 work_zone 路径的上两级(即 .hopstate 的绝对路径),
  instance_id = 本 run 的 instance_id,
  argv        = ["python3", "scripts/ssh_exec.py", "--config", "configs/x.json", "exec", "node1", "nvidia-smi"],
  cwd         = 可省(缺省工作区根),
  caller_step = 当前步号,如 "3.2"
)
```

argv 是列表,一项一个词,不拼 shell 字符串,没有管道和重定向。返回 `{returncode, stdout, stderr, duration_ms, truncated}`——非零 returncode 是正常返回,按业务判;stdout/stderr 各 64KB 截断并注明,要全文就让命令自己写文件再 read。每次执行的 argv/cwd/returncode/耗时都进该 run 的 hoplog,人不再逐条点批准,改为事后可查。

三种拒绝各怎么办:

- `APPROVAL_REQUIRED`(命令不在卡上):**这不是让你换个办法跑,是任务的授权范围要不要扩,归人决定。** 停下来问用户一句,说清三件事:这条命令是干什么的、是可逆探索还是会留下不可逆后果、为什么这个活需要它。用户说批 → 把前缀加进任务卡 `## 已批准命令` 节,`abort` 当前 run,用改好的卡重新 `run`(授权清单在 run 起跑时拍快照,跑着改不生效;已完成的步骤都是可逆探索,重跑无害)。用户说不批 → 这一条走载体的 Bash,照常弹窗批一次。**不许自己把命令加进卡、不许被拒后改走 Bash 绕过。**
- `COMMAND_FAILED`(命令本身跑挂:超时、找不到可执行文件、输出撞上限):按报文修命令或 timeout 再调,不换通道。
- `CWD_OUTSIDE_WORKSPACE`:cwd 必须在这个 run 的工作区内,改 cwd。

边界不变:`[commit]` 前置 check final/confirm、`confirm`/`ask` 停下问真人,一律照旧——run_approved_command 替代的只是载体逐条弹窗那一层,不替代卡上的闸;`hopjit` 自身恒拒。载体侧放行:`hopjit install-skill --carrier opencode` 的输出里有一行 `permission_note`,按它做两件事——把 opencode 配置里 `mcp.hopjit.enabled` 改为 `true`(安装缺省是 false,server 不启动则这个工具根本不存在),再放行 hopjit 的 `run_approved_command` 工具。没做之前走到已批准命令那一步会发现工具缺席:停下按本段 APPROVAL_REQUIRED 同款处置问用户,不要改走别的通道。

```bash
<CLI> --json run hop_tasks/<任务名>/<任务名>.md --state-dir .hopstate
→ step_ready: 步骤1
(就在本会话干活——该搜就搜、该读就读、该写就写,上下文全在)
<CLI> --json submit_and_fetch_next 1 --output '<产出>' --state-dir .hopstate --instance <id>
→ step_ready: 步骤2 …循环到终态
```

- 每条命令带全局 `--json`(缺省输出 YAML 给人看,机器消费显式要 JSON);返回单行 JSON 自己读懂按 `status` 分派,不用管道提取。**`--output` 的真实协议**(实撞:首提原始 YAML 被 JSON parser 拒):小产出传**与输出槽同名的 JSON 对象**——步骤声明 `+ → weather_data % yaml` 就传 `--output '{"weather_data": <值>}'`,不是把值本身裸贴;大产出写到响应给的 `output_path`(work_zone 内)再 `--output @<该路径>`(`@` 只贴参数最前面,路径须在 work_zone 内且用相对路径,绝不写进 JSON 字段值);
- 过程 `[check]` 步(非 final)如实判——**这正是引擎存在的意义**:判 false 会带你的失败说明重跑,不许"觉得差不多就 true";
- **`[check final]` 阅卷外移**(三权分拆:出题、答题在你,**阅卷不在你**):走到 check final 时,只要会话有派 subagent 的能力(opencode 内置 general 子代理,常态在场),就**恒外移**给一个全新子代理判定,无自由裁量。为什么:自驱把"写计划的、干活的、判合格的"压进同一个你——自己出题自己答题自己阅卷,判据再严也总有能绕的缝。派法三条:
  1. 阅卷子代理拿三样:**待判产出物全文 + check final 的判据原文 + 任务卡的背景/参考节**——**不给执行过程叙事**:阅卷人只对着产出与判据判,不被"我为什么这么做"说服;
  2. 子代理回 ok/note 判定与理由,**向引擎 submit 的仍是你**(哑搬运——不改判、不软化 note;不服判定就修产出重来,不许换个说法再问一遍);
  3. 无 subagent 能力时降级为判据硬化自判(见下条纪律,此时判据是唯一防线);
- **check 判据编写纪律**(出题时刻锁死——写卡时你还没有交付压力,此刻写死的判据引擎起跑后就禁改):判据必须是**执行者不能单方面满足的形态**——具体、可核对、指向产出物本身。**禁"或标注即可"式后门**;采信他人结论必须逐条给出采信理由,"同构""同理"不算理由;
- `[confirm]`/`[ask]` 停点**用 question 内置工具问用户**,等真人回答后注入(`--answer '{"value":"<用户给的真实值>"}'`)——不替答;`presented_data.present_inputs` 非空时先把这些字段原文完整展示再问,不缩略;
- **终态呈现分两层**:**契约层**——outputs 全字段完整交付,不摘要不漏不改写,跨载体不变;**渲染层**——单一 `text/markdown` 输出用你自己的呈现长处直接展示(可读的答复就是答复,不必套 YAML 壳),多字段/结构化输出保底 YAML 块防漏(多行字符串用 literal block)。**终态后顺手归档**——跑完确认交付即把任务目录挪 `hop_tasks/archive/`(归档规则写在管理节没人执行,动作提示挂在流程出口上);
- **手机通知(用户要了才发——引擎挂点,driver 只翻译意图)**:用户话语有钉钉通知意图("跑完钉钉通知我/钉我"——点名钉钉/钉渠道才算;光说"通知我"=对话里回话不推手机)或任务卡写明 → run 命令加 `--notify dingtalk`(flag 值=用户点名的渠道名)——渠道入任务的账,终态/停点引擎自动推卡片。发不发判断恒归引擎(话语渠道×凭证二与门,无配置文件环节),你只翻译意图不自行拼发送。发送失败引擎留 `[notify]` 行 → 转告用户一句(多半是 DINGTALK_WEBHOOK 凭证没配)照常干活;

### 2b. 步骤的注意力管理(缺省自驱,机械翻查可外包)

缺省**当前会话自己执行每一步**——上下文在场是 hop 的立身之本。两类例外(方向恰反,别混):**check final 的判定恒外移**(上节"阅卷外移"——那是把裁量权拿走,不是省注意力);**大面积机械翻查步可外包**(跨很多文件的核对/审计、长时间轮询等待、批量清点),全量结果灌回主对话会把后续步骤的判断力淹掉。这类步骤**在 subagent 能力可用时**可以派子代理承担**翻查半边**,规则三条:

1. **外包的只是翻查,判断与提交归你**——子代理带回"发现+证据+建议",裁定真伪、决定怎么办、向引擎 submit 的永远是你;
2. **派活输入必须自带该步全部所需上下文**——子代理看不到本对话:把步骤契约(要产出什么)、对话里已定的口径、要查证的具体疑点写全再派。派完不自查同一件事(别重复烧);
3. **拿不准某步算不算"机械翻查"就不外包**——判断类、创作类、需要对话语境的**执行**步骤永远留在当前会话(此条管的是"谁干活";check final 的"谁判卷"归阅卷外移条管,不受此条豁免——判定恰恰必须离开执行语境)。

subagent 能力不可用时就全部自驱——/hop 本就缺省自驱,外包只是可选优化,没有降级仪式。

### 3. 进展呈现(核心体验面)

每完成一步,给用户一行:

```
✅ 1 查来源(3 源已取)
✅ 2 交叉核对
▶️ 3.1 写初稿…
```

用户随时问进度:跑 `<CLI> --json status --state-dir .hopstate --instance <id>`,渲染成上面的形态(机器 JSON 不直接示人)。

### 4. 边跑边改计划(主动 replan)

干到某步发现**后面的计划**不对:

```bash
<CLI> --json submit_and_fetch_next <subtask-id> --replan '<新的未执行部分 markdown>' --proactive --state-dir .hopstate --instance <id>
```

三条规矩(引擎强制,先懂为什么):

- **只能改未执行的部分**——已做的是历史;正在做的这步做完再生效(发现当前方向就错了?那就别提交产出,改完计划再继续——效果一样且不需要新机制);
- **`[check final]` 不许改掉或跳过**——改路径可以,拆把关不行(随时可改计划的自由,靠把关点不可动来定价);
- 交付契约(Outputs)不许改——改策略不改目标。

### 5. 列 / 切 / 归档(多活并存的管理面)

**目录约定**(纯 driver 层,引擎零感知):

```
hop_tasks/
  <任务名>/
    <任务名>.md      ← 任务卡(spec+叙事,引擎读它;与目录同名——[[双链]]可达)
    …               ← 该任务的材料/草稿/证据,自由放(任务的东西住任务的家)
  current            ← 当前活指针(一行 instance_id)
  archive/<任务名>/   ← 归档=挪整个目录(不删——历史即账;固化提纯从这里捞)
  specs/<语义名>.md   ← 提纯件(可复用成品,distill 产出;非任务卡,list 不列它)
.hopstate/           ← 运行时状态照旧隐藏(机器账,人不直接读)
```

> **Obsidian/vault 增益**(零机制,天然获得):hop_tasks/ 在 vault 内时,任务卡可被 hopspec 插件可视化(步骤大纲=进度概览、commit 橙色=风险点一眼可见);材料引用直接写 `[[双链]]`——doc-ref 引擎语义与 Obsidian 双链本就是同一文法;archive/ 即可检索的工作史。

**`hop list`**(账驱动——任务↔实例的对应关系不另建映射,直接从引擎账上读):

1. 扫 `.hopstate/*/state.json`,读每份的 `spec_path`(该实例执行的 spec 文件绝对路径);
2. 只留 `spec_path` 落在本项目 `hop_tasks/` 下(不含 `archive/` 与 `specs/`——直接跑成品流程文件的实例不是"手头的活",不进清单)**且该任务卡现在还在活跃区**(`hop_tasks/<任务名>/` 下能找到同名卡——账上的 spec_path 是开工时的历史路径,归档挪目录不改账,光看账会把已归档的活误列回来)的实例;同一任务文件有多个实例时取最新的一个(state.json 修改时间最新);
3. 对留下的每个实例跑 `<CLI> --json status --state-dir .hopstate --instance <id>` 取进度(completed/total、current_step、是否停在确认点),渲染清单:

```
你手头的活:
▶️ 1. 调研X报告      3/5 步   ← 当前
⏸️ 2. 合同条款核对    1/4 步   (停在:需要你确认口径)
✅ 3. 周报            已完成
```

**切换**:说"hop 2"(序号)或 "hop 合同"(名字模糊匹配,多个命中就列出来问)→ 更新 `hop_tasks/current` → 展示该活进度 → 接着干。无参 hop 一声:有 current 续当前活;无则列清单问开新的还是接旧的。**current 失效自愈**:current 指向的实例查不到 / 文件已在 archive/ / current 文件缺失,一律按"无 current"走(列清单),顺手删掉失效的 current 文件——不报错不中断(指针是便利品,账才是权威)。

**归档 `hop archive <n>`(不是 delete——没有 delete)**:`hop_tasks/<任务名>/` **整个目录**挪入 `hop_tasks/archive/`(卡与材料一把全走——目录制的意义所在);`.hopstate` 实例目录与 hoplog 一律不动(历史即账)。**归档的正是当前活时,同步删 `hop_tasks/current`**(不清会留悬空指针——下次说 hop 会续一个已收起的活)。归档的活不进 list 缺省视图(`hop list all` 可看);想恢复就挪回来,账还在,续跑照常。跑完的活确认交付后同走归档(完成≠消失)。

**收没干完的活时,先问一句意图**(对用户零新词汇,一个"收起来"动作盖两种机制处置):活还没跑完就要归档时,用人话问:**"这个活还没干完——是不要了,还是先收起来、回头接着干?"**

- 答**"不要了"** → 先跑 `<CLI> --json abort --reason '<用户的话>' --state-dir .hopstate --instance <id>`(把引擎账记为已放弃——不终止的话账上永远显示"进行中",谎报状态),再挪目录归档。abort 是看不见的水管,**不向用户解释这个机制动作**。**废弃时若有半成品要交付**:交付物必须向用户标注"这活没走完最后的核对"——终检随实例消失了,这件事要对用户可见,不许把没把关的产出当正品交;
- 答**"回头再干"** → 只挪目录,账保留,恢复照续(上一段的承诺不变);
- 活已干完 → 什么都不问,直接收。**收干完的活时顺口带一句**:"这个流程要不要提纯成可复用的(下次同类活直接跑)?"——一句话提示不强推,用户没接话就只归档(动作提示挂流程出口上,与"终态后顺手归档"同理)。

**中断与接续(plan 不随对话死——核心价值)**:对话断了/新会话,hop 一声即回到当前活的进度上继续。**不必特意点名 hop**:同一会话里活跑着,说"继续"就继续(协议在场)。**用户只说"继续"而话语没点名对象时**(新会话开口、或会话里刚干过别的事):查账(current/status)发现有没干完的 hop 活 → **先跟用户确认一句再续**——"你是要继续《<任务名>》吗?上次干到 <进度>,停在 <哪步>"——确认了才续,不确认不动("继续"可能指对话里别的事,猜错就是拿着别人的话头干自己的活);明确说"继续上次的活/上次那个活到哪了"的,意图已点名,直接按无参 hop 走。

### 6. 提纯:干完的活 → 可复用 spec(`hop distill <n>`)

一个活跑通了,你手里就多了一份**被实战验证过的流程**。提纯把它从"一次性的任务卡"升格为"可复用的成品 spec"——今后同类活直接用 hopspec skill 跑,或作为下次 hop 升格同类任务的底稿。**触发从宽:用户的话里有"总结"的意思就主动做**——"总结一下这个活""沉淀下来""下次还要干这种事""固化成流程",不必等 distill 子命令或"可复用"这种精确措辞(`hop distill <n>` 是显式形态,留给要指定对象的场合)。对象缺省=刚干完/最近归档的活;活没干完不提纯——没跑通的流程没有"实战验证过"可言,先干完(用户对没干完的活说"总结",多半要的是进展汇报,给汇报即可)。

**不只 hop 任务能提纯——对话里直干完的活同样能总结(作者定 2026-08-28)**:"把刚才这个 PR 审查流程总结成可复用的"——活没走 hop 管护、没有引擎账,也照提。原料换成对话里的实际执行轨迹(真实走过的步骤序/中途撞的坑与修正/已拍的口径),四动作照做,外加一条 hop 任务提纯没有的活:**步骤类型现判**——对话轨迹没有类型标注,哪步是不可逆动作必须标 commit、哪里该补 check,此刻按升格要点判。验证面如实降档:对话直干没有引擎强制的把关记录,提纯件里的 check 是"该有"而非"验过"——诚实写明,不冒充与 hop 任务同级的实战验证。

**原料读三处(关键:拿终态,不拿初版)**:

- **任务卡的 Steps 终态**——replan 后引擎已把生效计划写回文件,这就是"跑通的那版";开工时的初版只活在 git/hoplog 里,不是提纯对象;
- **引擎账上的展开物**——`[subtask free]` 到步展开的实际子步只在引擎账上(status/hoplog,此场景属"用户要求复盘",可以读)。这段结构这次跑出来若是稳定形态,固化为显式子步;本质仍是"到时候看情况"的,保留 free;
- **任务卡的背景/处置记录**——口径与"为什么",供泛化时判断哪些是通用约束、哪些是这一次的专有语境;处置记录本身不带进提纯件。

**提纯四动作**:

1. **参数化**:这一次的具体值(对象名/路径/日期/阈值)提为 `Inputs`;实跑值降级为示范参数(写进输入注释,或并排放一份 sample 文件——examples 里 fact-check-sample 的同款形态);
2. **结构固化**:展开物按上条判"固化 vs 保留 free";这次没走到的分支(case else、失败路径)补审一眼——实战没验证过的路径,在提纯件对应步骤的 `>` 说明里如实标注"未经实跑验证",不冒充全验证;
3. **把关强化**:这次 check 打回抓过的缺口**写死进判据**——被实战抓过的坑是提纯件里最值钱的资产,一次性任务里"下次注意"的教训在这里变成引擎强制;缺 check 的段落顺手补上(成品 spec 的把关标准只高不低);
4. **语境泛化**:背景节改写成通用使用说明(这份 spec 干什么、输入怎么备、适用/不适用什么场景——内容章节缺省供给,写的就是未来每次执行的口径);"这一次"的专有语境全部剥离。

**落盘与验收**:产物落 `hop_tasks/specs/<语义名>.md`(/hop 的一切住 hop_tasks/ 一个家——活跃活、archive/、specs/ 三分区,项目根不另开目录〔作者定:太污染〕;specs/ 下无同名卡目录,list 的"活跃区同名卡"判据天然不把它误列成活;用户指定别处则从之),`<CLI> --json validate` 必须 0 error;提纯件开头加一行指回原任务(`[[<任务名>]]`——出处可溯,归档目录里躺着完整的实跑原料)。**给用户过目确认后才算落定**——提纯是"发布"性质的动作:从此这份 spec 会被反复跑,写错会被反复复制,这一眼比任何一次任务内 check 都值。**改既有提纯件同律**(复用中发现要改、或用户要求更新):改完 validate 0 error+用户过目确认才生效——改坏同样被反复复制。原任务目录照常归档,一动不动。

### 7. 决策:把待拍的板逐个说清楚,拍板过程存档(`hop 决策`,作者定 2026-09-04)

用户说 `hop 决策`(或"有什么要我拍的""待决策的过一遍"这类话)时,进入决策会话。三段式:**收集 → 逐个呈报拍板 → 存档**。

**① 收集待决策点**。扫当前对话里挂着的决策点(上报过但还没拍的、刚冒出来的),加上任务卡背景节/todo 卡里标了"待作者拍板/待拍/decision pending"的项。列个清单先给用户看一眼(一行一个,只写标题):"手头有 N 个要你拍的板:1…… 2…… 一个一个来。"没有待决策点就如实说"目前没有挂着的板",不硬凑。

**② 逐个呈报,一次只呈一个**。每个决策点按元规范"上报决策上下文自足"四件套呈报,判据是**没跟着干活的人一遍读懂、不追问任何背景就能拍板**:

1. **问题怎么来的**——这个决策点从哪冒出来(哪次实撞/哪份报告/哪个改动被拦),来龙去脉讲全;
2. **现状事实**——盘点数据、涉及范围、已核实的机制真相。技术名词第一次出现就地解释("保护壳(一个事务容器,作用是子树失败时降级兜底不炸整层)"这种写法),不用只有干活的人才懂的代号;
3. **每个备选做什么、代价是什么**——不是只给标签:每条路展开说"选它之后会发生什么、要干哪些活、什么东西变好、什么东西变差、风险在哪、代价多大(能量化就量化)"。正反两面都说,不许把倾向项写得全是好话;
4. **倾向与理由**——明确说倾向哪个,理由逐条。

呈报后用 question 内置工具请拍板(列出选项,倾向项放第一个标"推荐",等用户回答)。**拍完一个再呈下一个**——不许把 N 个决策点挤进一条消息一把问完(用户对着一坨并排的问题没法逐个深想,这正是本机制要消灭的形态)。用户对某个点追问就地展开,追问后改了倾向如实改。

**③ 每拍完一个板,当场存档**。落 `todo/decision/`(目录不存在则建),一板一文件,命名 `YYYYMMDD-<短语义名>.md`。内容结构(呈报原文+拍板结果全存,判据是三个月后翻出来不需要任何对话记忆就能看懂当时为什么这么定):

```markdown
# 决策:<标题一句话>

- 时间:<date '+%Y-%m-%dT%H:%M%z' 取真实时间>
- git 版本:<git rev-parse --short HEAD>(<当前分支/detached>)
- 拍板人:作者
- 结论:**<选了哪项>**

## 背景(问题怎么来的)
<呈报原文第 1 部分>

## 现状事实
<呈报原文第 2 部分>

## 备选与代价
<呈报原文第 3 部分,逐案全文>

## 倾向与理由
<呈报时的倾向与理由;拍板结果与倾向不一致时,把用户改选的理由(用户说了就记,没说就写"作者未述理由")单独一行记上>

## 拍板过程
<拍板时用户的原话/选项;有追问往返的,把追问与解答的要点逐条记下——追问暴露的信息缺口正是下次呈报要长记性的地方>

## 落地去向
<这个板拍完由哪个批次/哪张卡承接,落地后回填 commit 号——建档时先写承接处,落地补号>
```

存档后给用户一行确认:"已存档 todo/decision/<文件名>"。全部拍完后收尾一句总结(拍了几个、各自结论一行、落地去向)。

三条纪律:

- **存档是给未来读者写的**,不是会话日志——呈报文字本来就按"零背景读懂"写,原样入档即可;禁止入档时压缩成只有当事人读得懂的摘要;
- **决策文件不改写历史**:拍过的板事后要翻案,新开一份决策文件记新板并在两份里互相指路(`翻案自/被翻案于 <文件名>`),旧文件原文不动——决策档案是账,不是现行规则库(现行规则归设计文档与任务卡);
- **git 版本号记录的是拍板时刻主区 HEAD**——决策依据的代码现场可回溯(`git show <号>` 即到当时);若拍板发生在 worktree 语境,主区 HEAD 与 worktree 基线都记。

## 输出纪律

- **压缩后不凭记忆驱动**(skill 正文走对话通道,上下文压缩时会退化成摘要——协议细节最先丢):发现自己对协议细节不确定(--output 怎么传、阅卷怎么派、归档先问什么——刚经历过压缩的典型体感),**先重读盘上的本 skill 文件再继续**,不凭模糊记忆猜协议。盘上真身恒新鲜,缺的只是"去重读"这个动作;任务状态本就不怕压缩(引擎账+任务卡在盘上,hop 一声 一声即接续);
- **hoplog 分场景**:正常执行与状态判断**不翻 hoplog**(状态权威=引擎响应与 status,拿日志猜状态必错);**用户明确要求复盘、诊断或审计时可以读**,引用过程证据要与 state/响应对账——日志是过程记录,不覆盖状态权威;
- 对用户零行话:不说 spec/介入点/replan/abort/实例,说"计划/需要你确认/改一下后面的步骤/这活还没干完"。
- **派活文字零黑话(2026-08-28 作者定——对 LLM 更要说人话,不是更可以省)**:给 subagent 的派活 prompt、任务卡、阅卷包判据,全部用完整的话写——判据、停止条件、命令逐条写全,不用只有写的人自己懂的缩写代号。LLM 对压缩表述的理解比人更容易出错且非常不稳定:人读不懂会反问,LLM 不会反问、按猜的理解直接执行且不出声,误解指令的 subagent 会带着错误理解跑完全程(实撞:看护 subagent 把"返回即下班"理解成可以中途交卷,两次误收工)。

Files in this skill

  • SKILL-mcp.md6 KB
  • SKILL.md15.6 KB
  • hop-skill.md36.4 KB
  • references/cli-discovery.md2.1 KB
  • references/discovery.md4.9 KB
  • references/driver-subagent.md5.8 KB
  • references/step-execution-rules.md13 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.