helloagents 3.0.11-beta.1 → 3.0.12-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +7 -13
- package/README_CN.md +7 -13
- package/bootstrap-lite.md +3 -2
- package/bootstrap.md +3 -2
- package/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/scripts/notify.mjs +24 -1
- package/scripts/turn-state.mjs +24 -0
- package/scripts/turn-stop-gate.mjs +92 -0
- package/skills/hello-verify/SKILL.md +1 -1
- package/skills/helloagents/SKILL.md +1 -1
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
{
|
|
10
10
|
"name": "helloagents",
|
|
11
11
|
"description": "Quality-driven orchestration kernel for AI CLIs: intelligent routing, quality verification, safety guards, and notifications",
|
|
12
|
-
"version": "3.0.
|
|
12
|
+
"version": "3.0.12-beta.1",
|
|
13
13
|
"source": "./",
|
|
14
14
|
"author": {
|
|
15
15
|
"name": "HelloWind",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "helloagents",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.12-beta.1",
|
|
4
4
|
"description": "HelloAGENTS — The orchestration kernel that makes any AI CLI smarter. Adds intelligent routing, quality verification (Ralph Loop), safety guards, and notifications.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "HelloWind",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "helloagents",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.12-beta.1",
|
|
4
4
|
"description": "HelloAGENTS — Quality-driven orchestration kernel for AI CLIs with intelligent routing, quality verification (Ralph Loop), safety guards, and notifications.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "HelloWind",
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
**A workflow layer for AI coding CLIs: skills, project knowledge, delivery checks, safer config writes, and resumable execution.**
|
|
10
10
|
|
|
11
|
-
[](./package.json)
|
|
12
12
|
[](https://www.npmjs.com/package/helloagents)
|
|
13
13
|
[](./package.json)
|
|
14
14
|
[](./skills)
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
## Contents
|
|
31
31
|
|
|
32
32
|
- [What HelloAGENTS Does](#what-helloagents-does)
|
|
33
|
-
- [What Changed Since v3.0.
|
|
33
|
+
- [What Changed Since v3.0.11](#what-changed-since-v3011)
|
|
34
34
|
- [Core Features](#core-features)
|
|
35
35
|
- [Quick Start](#quick-start)
|
|
36
36
|
- [CLI Management](#cli-management)
|
|
@@ -77,19 +77,13 @@ HelloAGENTS adds a workflow layer on top of Claude Code, Gemini CLI, and Codex C
|
|
|
77
77
|
| Completion is vague | Natural language says “done” | Delivery checks use state, evidence, and verification |
|
|
78
78
|
| Config writes are risky | CLI files can drift | Install, update, cleanup, and doctor flows check managed files |
|
|
79
79
|
|
|
80
|
-
## What Changed Since v3.0.
|
|
80
|
+
## What Changed Since v3.0.11
|
|
81
81
|
|
|
82
|
-
These are the main user-visible runtime
|
|
82
|
+
These are the main user-visible runtime changes in `v3.0.12`, compared with `v3.0.11`:
|
|
83
83
|
|
|
84
|
-
-
|
|
85
|
-
-
|
|
86
|
-
-
|
|
87
|
-
- The final closeout fallback wording no longer sounds like it is waiting for another manual approval after the task is already complete.
|
|
88
|
-
- Main-agent delivery now uses structured `turn-state` values such as `complete`, `waiting`, and `blocked`; stop, notify, and closeout no longer infer completion from natural-language text.
|
|
89
|
-
- Workflow recovery now uses the current `state_path`, with session-scoped state files under `.helloagents/sessions/<branch>/<session-or-default>/STATE.md`.
|
|
90
|
-
- The old project-root state fallback has been removed, so recovery follows one current state path.
|
|
91
|
-
- Codex standby/global install, refresh, cleanup, and doctor checks are stricter: managed `notify` entries are marked, multiline `notify` arrays are preserved, and user-owned `model_instructions_file`, `notify`, and non-managed `codex_hooks` are kept during restore.
|
|
92
|
-
- Codex global mode now refreshes the home read root, local plugin root, marketplace entry, enabled plugin block, and cache copy after reinstall, update, or local branch changes.
|
|
84
|
+
- Explicit `~auto` and `~loop` no longer get a free pass to stop a turn early. Before the runtime accepts the turn end, it now checks whether the main agent wrote a valid structured stop state.
|
|
85
|
+
- `waiting` and `blocked` turn states now require both a `reasonCategory` and a concrete `reason`, so only real blockers can pause the workflow instead of vague “next step” hand-offs.
|
|
86
|
+
- The stop hook and Codex turn-complete notification path now enforce the same gate, reducing cases where work still should continue but the agent stops as if it is waiting for approval.
|
|
93
87
|
|
|
94
88
|
## Core Features
|
|
95
89
|
|
package/README_CN.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
**面向 AI 编码 CLI 的工作流层:技能、知识库、交付检查、更安全的配置写入,以及可恢复的执行流程。**
|
|
10
10
|
|
|
11
|
-
[](./package.json)
|
|
12
12
|
[](https://www.npmjs.com/package/helloagents)
|
|
13
13
|
[](./package.json)
|
|
14
14
|
[](./skills)
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
## 目录
|
|
31
31
|
|
|
32
32
|
- [HelloAGENTS 做什么](#helloagents-做什么)
|
|
33
|
-
- [相对 v3.0.
|
|
33
|
+
- [相对 v3.0.11 的真实变化](#相对-v3011-的真实变化)
|
|
34
34
|
- [核心功能](#核心功能)
|
|
35
35
|
- [快速开始](#快速开始)
|
|
36
36
|
- [CLI 管理](#cli-管理)
|
|
@@ -77,19 +77,13 @@ HelloAGENTS 叠加在 Claude Code、Gemini CLI 和 Codex CLI 之上,帮助模
|
|
|
77
77
|
| 完成态模糊 | 自然语言说“完成” | 按状态、证据和验证结果交付 |
|
|
78
78
|
| 配置容易漂移 | CLI 文件可能不一致 | 安装、更新、清理和 doctor 会检查受管文件 |
|
|
79
79
|
|
|
80
|
-
## 相对 v3.0.
|
|
80
|
+
## 相对 v3.0.11 的真实变化
|
|
81
81
|
|
|
82
|
-
下面是当前 `v3.0.
|
|
82
|
+
下面是当前 `v3.0.12` 相对 `v3.0.11` 的主要运行时变化:
|
|
83
83
|
|
|
84
|
-
-
|
|
85
|
-
-
|
|
86
|
-
-
|
|
87
|
-
- 最终收尾的兜底文案不再写成“等待下一步指示”,避免任务已经完成时仍表现得像在等人工批准。
|
|
88
|
-
- 主代理交付改用结构化 `turn-state`,明确区分 `complete`、`waiting`、`blocked`;stop、notify、收尾流程不再从自然语言里猜完成态。
|
|
89
|
-
- 工作流恢复改为读取当前 `state_path`,状态文件按会话写入 `.helloagents/sessions/<branch>/<session-or-default>/STATE.md`。
|
|
90
|
-
- 移除旧的项目根状态文件回退逻辑,恢复流程只走当前状态路径。
|
|
91
|
-
- Codex 标准/全局模式的安装、刷新、清理和 doctor 检查更严格:受管 `notify` 会带标记,多行 `notify` 数组可保留,用户自己的 `model_instructions_file`、`notify`、非托管 `codex_hooks` 会在恢复时保留。
|
|
92
|
-
- Codex 全局模式在重装、更新或本地切分支后,会同步刷新 home 读取根、本地插件根目录、marketplace 条目、插件启用段和缓存副本。
|
|
84
|
+
- 显式使用 `~auto` 和 `~loop` 时,运行时不再默认接受中途停下;主代理结束本轮前,必须先写出有效的结构化停下状态。
|
|
85
|
+
- `waiting` 和 `blocked` 现在必须同时带 `reasonCategory` 和具体 `reason`,只有真实阻塞才能暂停流程,不再接受含糊的“下一步”式停顿。
|
|
86
|
+
- stop hook 和 Codex 的 turn-complete 通知链路现在共用同一层门控,减少任务本应继续执行却表现得像在等批准的情况。
|
|
93
87
|
|
|
94
88
|
## 核心功能
|
|
95
89
|
|
package/bootstrap-lite.md
CHANGED
|
@@ -123,8 +123,9 @@
|
|
|
123
123
|
### 收尾状态信号
|
|
124
124
|
- 为避免运行时从自然语言、图标或格式反推“完成 / 等待输入”,主代理在本轮最终收尾前必须先调用 `scripts/turn-state.mjs write`
|
|
125
125
|
- 本轮已完成且不再等待用户输入 → 写 `kind=complete`、`role=main`
|
|
126
|
-
- 因阻塞判定等待用户输入、确认、授权或补充信息 → 写 `kind=waiting`、`role=main`
|
|
127
|
-
- 因错误、缺少前置条件或外部依赖而本轮停下 → 写 `kind=blocked`、`role=main`
|
|
126
|
+
- 因阻塞判定等待用户输入、确认、授权或补充信息 → 写 `kind=waiting`、`role=main`,并同时写 `reasonCategory` 与 `reason`
|
|
127
|
+
- 因错误、缺少前置条件或外部依赖而本轮停下 → 写 `kind=blocked`、`role=main`,并同时写 `reasonCategory` 与 `reason`
|
|
128
|
+
- `reasonCategory` 只允许:`ambiguity`、`missing-input`、`missing-file`、`missing-credential`、`unauthorized-side-effect`、`high-risk-confirmation`、`external-dependency`、`error`
|
|
128
129
|
- 子代理不得写 turn-state;子代理结束只直接返回结果,不为主代理代写完成态
|
|
129
130
|
|
|
130
131
|
## 交互规则
|
package/bootstrap.md
CHANGED
|
@@ -123,8 +123,9 @@
|
|
|
123
123
|
### 收尾状态信号
|
|
124
124
|
- 为避免运行时从自然语言、图标或格式反推“完成 / 等待输入”,主代理在本轮最终收尾前必须先调用 `scripts/turn-state.mjs write`
|
|
125
125
|
- 本轮已完成且不再等待用户输入 → 写 `kind=complete`、`role=main`
|
|
126
|
-
- 因阻塞判定等待用户输入、确认、授权或补充信息 → 写 `kind=waiting`、`role=main`
|
|
127
|
-
- 因错误、缺少前置条件或外部依赖而本轮停下 → 写 `kind=blocked`、`role=main`
|
|
126
|
+
- 因阻塞判定等待用户输入、确认、授权或补充信息 → 写 `kind=waiting`、`role=main`,并同时写 `reasonCategory` 与 `reason`
|
|
127
|
+
- 因错误、缺少前置条件或外部依赖而本轮停下 → 写 `kind=blocked`、`role=main`,并同时写 `reasonCategory` 与 `reason`
|
|
128
|
+
- `reasonCategory` 只允许:`ambiguity`、`missing-input`、`missing-file`、`missing-credential`、`unauthorized-side-effect`、`high-risk-confirmation`、`external-dependency`、`error`
|
|
128
129
|
- 子代理不得写 turn-state;子代理结束只直接返回结果,不为主代理代写完成态
|
|
129
130
|
|
|
130
131
|
## 交互规则
|
package/gemini-extension.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "helloagents",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.12-beta.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "HelloAGENTS — The orchestration kernel that makes any AI CLI smarter. Adds intelligent routing, quality verification (Ralph Loop), safety guards, and notifications.",
|
|
6
6
|
"author": "HelloWind",
|
package/scripts/notify.mjs
CHANGED
|
@@ -93,6 +93,19 @@ function runDeliveryGate(payload) {
|
|
|
93
93
|
});
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
function runTurnStopGate(payload) {
|
|
97
|
+
return runGateScript({
|
|
98
|
+
payload,
|
|
99
|
+
host: HOST,
|
|
100
|
+
scriptPath: join(__dirname, 'turn-stop-gate.mjs'),
|
|
101
|
+
source: 'turn-stop-gate',
|
|
102
|
+
blockEvent: 'turn_stop_blocked',
|
|
103
|
+
timeout: 30_000,
|
|
104
|
+
appendReplayEvent,
|
|
105
|
+
output,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
96
109
|
function readMainTurnState(cwd) {
|
|
97
110
|
const turnState = readTurnState(cwd);
|
|
98
111
|
return turnState?.role === 'main' ? turnState : null;
|
|
@@ -197,8 +210,11 @@ function cmdStop() {
|
|
|
197
210
|
const payload = readStdinJson();
|
|
198
211
|
const cwd = payload.cwd || process.cwd();
|
|
199
212
|
const turnState = readMainTurnState(cwd);
|
|
213
|
+
if (runTurnStopGate(payload)) {
|
|
214
|
+
if (turnState && turnState.kind !== 'complete') consumeMainTurnState(cwd, turnState);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
200
217
|
const shouldProcess = shouldProcessCloseout(turnState);
|
|
201
|
-
clearRouteContext();
|
|
202
218
|
if (shouldProcess && runRalphLoop(payload)) {
|
|
203
219
|
consumeMainTurnState(cwd, turnState);
|
|
204
220
|
notifyByLevel('warning', buildNotifyExtra(payload));
|
|
@@ -215,6 +231,7 @@ function cmdStop() {
|
|
|
215
231
|
notifyByLevel('complete', buildNotifyExtra(payload), settings);
|
|
216
232
|
}
|
|
217
233
|
consumeMainTurnState(cwd, turnState);
|
|
234
|
+
clearRouteContext();
|
|
218
235
|
emptySuppress();
|
|
219
236
|
}
|
|
220
237
|
|
|
@@ -242,9 +259,14 @@ function cmdCodexNotify() {
|
|
|
242
259
|
|
|
243
260
|
const cwd = data.cwd || process.cwd();
|
|
244
261
|
const turnState = readMainTurnState(cwd);
|
|
262
|
+
if (runTurnStopGate(data)) {
|
|
263
|
+
if (turnState && turnState.kind !== 'complete') consumeMainTurnState(cwd, turnState);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
245
266
|
if (!turnState) return;
|
|
246
267
|
if (turnState.kind !== 'complete') {
|
|
247
268
|
consumeMainTurnState(cwd, turnState);
|
|
269
|
+
clearRouteContext();
|
|
248
270
|
return;
|
|
249
271
|
}
|
|
250
272
|
|
|
@@ -262,6 +284,7 @@ function cmdCodexNotify() {
|
|
|
262
284
|
|
|
263
285
|
notifyByLevel('complete', buildNotifyExtra(data), settings);
|
|
264
286
|
consumeMainTurnState(cwd, turnState);
|
|
287
|
+
clearRouteContext();
|
|
265
288
|
}
|
|
266
289
|
|
|
267
290
|
const cmd = process.argv[2] || '';
|
package/scripts/turn-state.mjs
CHANGED
|
@@ -9,6 +9,16 @@ const TURN_STATE_PATH = join(homedir(), '.helloagents', 'runtime', 'turn-state.j
|
|
|
9
9
|
const TURN_STATE_TTL_MS = 30 * 60 * 1000
|
|
10
10
|
const VALID_KINDS = new Set(['complete', 'waiting', 'blocked', 'progress'])
|
|
11
11
|
const VALID_ROLES = new Set(['main', 'subagent'])
|
|
12
|
+
const VALID_REASON_CATEGORIES = new Set([
|
|
13
|
+
'ambiguity',
|
|
14
|
+
'missing-input',
|
|
15
|
+
'missing-file',
|
|
16
|
+
'missing-credential',
|
|
17
|
+
'unauthorized-side-effect',
|
|
18
|
+
'high-risk-confirmation',
|
|
19
|
+
'external-dependency',
|
|
20
|
+
'error',
|
|
21
|
+
])
|
|
12
22
|
|
|
13
23
|
function normalizePath(filePath = '') {
|
|
14
24
|
return filePath ? normalize(resolve(filePath)) : ''
|
|
@@ -44,6 +54,10 @@ function getTurnStateKey(cwd = process.cwd()) {
|
|
|
44
54
|
function normalizeTurnState(input = {}) {
|
|
45
55
|
const kind = typeof input.kind === 'string' ? input.kind.trim().toLowerCase() : ''
|
|
46
56
|
const role = typeof input.role === 'string' ? input.role.trim().toLowerCase() : 'main'
|
|
57
|
+
const reasonCategory = typeof input.reasonCategory === 'string'
|
|
58
|
+
? input.reasonCategory.trim().toLowerCase()
|
|
59
|
+
: ''
|
|
60
|
+
const reason = typeof input.reason === 'string' ? input.reason.trim() : ''
|
|
47
61
|
|
|
48
62
|
return {
|
|
49
63
|
kind: VALID_KINDS.has(kind) ? kind : '',
|
|
@@ -51,6 +65,8 @@ function normalizeTurnState(input = {}) {
|
|
|
51
65
|
phase: typeof input.phase === 'string' ? input.phase.trim().toLowerCase() : '',
|
|
52
66
|
source: typeof input.source === 'string' && input.source.trim() ? input.source.trim() : 'manual',
|
|
53
67
|
requiresDeliveryGate: Boolean(input.requiresDeliveryGate),
|
|
68
|
+
reasonCategory: VALID_REASON_CATEGORIES.has(reasonCategory) ? reasonCategory : '',
|
|
69
|
+
reason,
|
|
54
70
|
}
|
|
55
71
|
}
|
|
56
72
|
|
|
@@ -105,6 +121,12 @@ export function writeTurnState(cwd = process.cwd(), input = {}) {
|
|
|
105
121
|
if (!key || !normalized.kind) {
|
|
106
122
|
throw new Error('turn-state requires cwd and a valid kind')
|
|
107
123
|
}
|
|
124
|
+
if (
|
|
125
|
+
(normalized.kind === 'waiting' || normalized.kind === 'blocked')
|
|
126
|
+
&& (!normalized.reasonCategory || !normalized.reason)
|
|
127
|
+
) {
|
|
128
|
+
throw new Error('turn-state waiting/blocked requires reasonCategory and reason')
|
|
129
|
+
}
|
|
108
130
|
|
|
109
131
|
const store = readStore()
|
|
110
132
|
const payload = {
|
|
@@ -123,6 +145,8 @@ export function writeTurnState(cwd = process.cwd(), input = {}) {
|
|
|
123
145
|
role: normalized.role,
|
|
124
146
|
phase: normalized.phase,
|
|
125
147
|
requiresDeliveryGate: normalized.requiresDeliveryGate,
|
|
148
|
+
reasonCategory: normalized.reasonCategory,
|
|
149
|
+
reason: normalized.reason,
|
|
126
150
|
},
|
|
127
151
|
})
|
|
128
152
|
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
|
|
4
|
+
import { getApplicableRouteContext } from './runtime-context.mjs'
|
|
5
|
+
import { readTurnState } from './turn-state.mjs'
|
|
6
|
+
import { getWorkflowRecommendation } from './workflow-state.mjs'
|
|
7
|
+
|
|
8
|
+
const ENFORCED_COMMANDS = new Set(['auto', 'loop'])
|
|
9
|
+
const ALLOWED_STOP_REASON_CATEGORIES = [
|
|
10
|
+
'ambiguity',
|
|
11
|
+
'missing-input',
|
|
12
|
+
'missing-file',
|
|
13
|
+
'missing-credential',
|
|
14
|
+
'unauthorized-side-effect',
|
|
15
|
+
'high-risk-confirmation',
|
|
16
|
+
'external-dependency',
|
|
17
|
+
'error',
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
function readStdinJson() {
|
|
21
|
+
try {
|
|
22
|
+
return JSON.parse(readFileSync(0, 'utf-8'))
|
|
23
|
+
} catch {
|
|
24
|
+
return {}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function buildWorkflowHint(cwd) {
|
|
29
|
+
const recommendation = getWorkflowRecommendation(cwd)
|
|
30
|
+
if (!recommendation) return ''
|
|
31
|
+
return [
|
|
32
|
+
`当前工作流:${recommendation.summary}`,
|
|
33
|
+
`建议路径:${recommendation.nextPath}`,
|
|
34
|
+
recommendation.guidance,
|
|
35
|
+
].filter(Boolean).join('\n')
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function buildBlockReason(routeContext, detail, cwd) {
|
|
39
|
+
const commandLabel = `~${routeContext.skillName}`
|
|
40
|
+
const workflowHint = buildWorkflowHint(cwd)
|
|
41
|
+
return [
|
|
42
|
+
`[HelloAGENTS Runtime] 显式 ${commandLabel} 本轮不应直接停下。`,
|
|
43
|
+
detail,
|
|
44
|
+
workflowHint,
|
|
45
|
+
'若无真实阻塞,请继续沿当前路径执行。',
|
|
46
|
+
`若确需停下,先调用 \`scripts/turn-state.mjs write\` 写结构化状态:\`kind=waiting\` 或 \`kind=blocked\`,并同时填写 \`reasonCategory\` 与 \`reason\`。`,
|
|
47
|
+
`允许的 \`reasonCategory\`:${ALLOWED_STOP_REASON_CATEGORIES.join(' | ')}。`,
|
|
48
|
+
].filter(Boolean).join('\n')
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function getMainTurnState(cwd) {
|
|
52
|
+
const turnState = readTurnState(cwd)
|
|
53
|
+
return turnState?.role === 'main' ? turnState : null
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function validateTurnState(routeContext, turnState, cwd) {
|
|
57
|
+
if (!turnState) {
|
|
58
|
+
return buildBlockReason(routeContext, '缺少主代理 turn-state。', cwd)
|
|
59
|
+
}
|
|
60
|
+
if (turnState.kind === 'complete') {
|
|
61
|
+
return ''
|
|
62
|
+
}
|
|
63
|
+
if (turnState.kind === 'waiting' || turnState.kind === 'blocked') {
|
|
64
|
+
if (turnState.reasonCategory && turnState.reason) {
|
|
65
|
+
return ''
|
|
66
|
+
}
|
|
67
|
+
return buildBlockReason(
|
|
68
|
+
routeContext,
|
|
69
|
+
`当前 turn-state 为 \`${turnState.kind}\`,但缺少 \`reasonCategory\` 或 \`reason\`。`,
|
|
70
|
+
cwd,
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
return buildBlockReason(routeContext, `当前 turn-state 为 \`${turnState.kind}\`,不能作为本轮结束状态。`, cwd)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function main() {
|
|
77
|
+
const payload = readStdinJson()
|
|
78
|
+
const cwd = payload.cwd || process.cwd()
|
|
79
|
+
const routeContext = getApplicableRouteContext({ cwd })
|
|
80
|
+
|
|
81
|
+
if (!routeContext || !ENFORCED_COMMANDS.has(routeContext.skillName)) {
|
|
82
|
+
process.stdout.write(JSON.stringify({ decision: 'continue' }))
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const reason = validateTurnState(routeContext, getMainTurnState(cwd), cwd)
|
|
87
|
+
process.stdout.write(JSON.stringify(reason ? { decision: 'block', reason } : { decision: 'continue' }))
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
|
|
91
|
+
main()
|
|
92
|
+
}
|
|
@@ -76,7 +76,7 @@ description: 声称工作完成前、提交代码前、创建 PR 前、报告任
|
|
|
76
76
|
5. 若当前存在方案包并准备最终收尾,优先调用 `scripts/closeout-state.mjs write` 写 `.helloagents/.ralph-closeout.json`,记录 `requirementsCoverage` 与 `deliveryChecklist` 两项结论;两项都必须包含 `status`(`PASS` / `BLOCKED`)和 `summary`
|
|
77
77
|
6. 若当前方案包要求 `review-first`,必须先确认 `.helloagents/.ralph-review.json` 已通过 `scripts/review-state.mjs write` 写成最新结构化证据;不要把审查自然语言消息直接当成交付证据
|
|
78
78
|
7. 若 `contract.json` 中 `ui.visualValidation.required=true`,必须确认 `.helloagents/.ralph-visual.json` 已通过 `scripts/visual-state.mjs write` 写成最新结构化证据;若没有视觉验收证据,不得把本轮视为 UI 可交付
|
|
79
|
-
8. 准备以本轮最终收尾消息报告完成时,先调用 `scripts/turn-state.mjs write` 写 `kind=complete`、`role=main`;若因阻塞判定等待输入或因前置条件缺失而停下,写 `kind=waiting` 或 `kind=blocked`,不要让运行时从自然语言消息里猜状态
|
|
79
|
+
8. 准备以本轮最终收尾消息报告完成时,先调用 `scripts/turn-state.mjs write` 写 `kind=complete`、`role=main`;若因阻塞判定等待输入或因前置条件缺失而停下,写 `kind=waiting` 或 `kind=blocked`,并同时写 `reasonCategory` 与 `reason`,不要让运行时从自然语言消息里猜状态
|
|
80
80
|
|
|
81
81
|
## 需求追踪验证
|
|
82
82
|
|
|
@@ -7,7 +7,7 @@ description: 每次对话开始时使用 — 建立质量驱动工作流,通
|
|
|
7
7
|
|
|
8
8
|
主代理触发或读取任意 skill 时,只有在该条消息是本轮最终收尾消息时,才按当前已加载 bootstrap 规则包装 HelloAGENTS 外层输出格式;任何 skill 若在本轮明确要求输出停顿、确认或总结,对应消息也必须同时满足相同条件。
|
|
9
9
|
子代理只豁免路由与收尾要求,直接执行任务;安全、质量、验证和失败处理规则仍持续生效,且不得包装 HelloAGENTS 外层输出格式。所有流式内容、进度或状态汇报、中间文本,以及任何仍将继续执行的文本,都不得触发外层格式。
|
|
10
|
-
主代理在本轮最终收尾前,如要报告“已完成 / 等待输入 / 本轮阻塞”,必须先调用 `scripts/turn-state.mjs write` 写机器可读的 turn-state
|
|
10
|
+
主代理在本轮最终收尾前,如要报告“已完成 / 等待输入 / 本轮阻塞”,必须先调用 `scripts/turn-state.mjs write` 写机器可读的 turn-state;不要让运行时再从自然语言或图标反推状态。若写 `kind=waiting` 或 `kind=blocked`,还必须同时写 `reasonCategory` 与 `reason`。子代理不得写 turn-state。
|
|
11
11
|
|
|
12
12
|
`.helloagents/` 在所有 skill 中都统一按项目级存储路径理解:项目本地 `.helloagents/` 继续承担激活信号与 `.ralph-*.json` 等运行态文件;状态文件只使用 `state_path`(实际位于 `sessions/{branch}/{session-or-default}/STATE.md`);若 `project_store_mode=repo-shared`,`context.md`、`guidelines.md`、`DESIGN.md`、`verify.yaml`、`modules/`、`plans/`、`archive/` 按当前上下文中已注入的“当前项目存储”/“项目知识/方案目录”解析,不要假定这些文件一定实际位于当前工作树中。
|
|
13
13
|
|