@brawnen/agent-harness-cli 0.1.0
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/LICENSE +21 -0
- package/README.md +224 -0
- package/README.zh-CN.md +232 -0
- package/bin/agent-harness.js +6 -0
- package/package.json +46 -0
- package/src/commands/audit.js +110 -0
- package/src/commands/delivery.js +497 -0
- package/src/commands/docs.js +251 -0
- package/src/commands/gate.js +236 -0
- package/src/commands/init.js +711 -0
- package/src/commands/report.js +272 -0
- package/src/commands/state.js +274 -0
- package/src/commands/status.js +493 -0
- package/src/commands/task.js +316 -0
- package/src/commands/verify.js +173 -0
- package/src/index.js +101 -0
- package/src/lib/audit-store.js +80 -0
- package/src/lib/delivery-policy.js +219 -0
- package/src/lib/output-policy.js +266 -0
- package/src/lib/project-config.js +235 -0
- package/src/lib/runtime-paths.js +46 -0
- package/src/lib/state-store.js +510 -0
- package/src/lib/task-core.js +490 -0
- package/src/lib/workflow-policy.js +307 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 brawnen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# @brawnen/agent-harness-cli
|
|
2
|
+
|
|
3
|
+
[中文](README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
`@brawnen/agent-harness-cli` is the Node.js CLI for `agent-harness`.
|
|
6
|
+
|
|
7
|
+
It is the runtime layer that turns protocol rules into a working task loop with:
|
|
8
|
+
|
|
9
|
+
- initialization
|
|
10
|
+
- task state
|
|
11
|
+
- verification
|
|
12
|
+
- reports
|
|
13
|
+
- gating
|
|
14
|
+
- audit
|
|
15
|
+
- delivery
|
|
16
|
+
- documentation scaffolding
|
|
17
|
+
|
|
18
|
+
## Current Coverage
|
|
19
|
+
|
|
20
|
+
The CLI currently includes these commands:
|
|
21
|
+
|
|
22
|
+
- `init`
|
|
23
|
+
- `status`
|
|
24
|
+
- `task`
|
|
25
|
+
- `state`
|
|
26
|
+
- `verify`
|
|
27
|
+
- `report`
|
|
28
|
+
- `gate`
|
|
29
|
+
- `audit`
|
|
30
|
+
- `delivery`
|
|
31
|
+
- `docs`
|
|
32
|
+
|
|
33
|
+
The current implementation also covers:
|
|
34
|
+
|
|
35
|
+
- `--dry-run`
|
|
36
|
+
- `--protocol-only`
|
|
37
|
+
- host rule injection
|
|
38
|
+
- base project config generation
|
|
39
|
+
- minimal `.codex/hooks.json` integration
|
|
40
|
+
|
|
41
|
+
## Current Boundaries
|
|
42
|
+
|
|
43
|
+
The CLI is already usable, but it is still an evolving implementation.
|
|
44
|
+
|
|
45
|
+
It currently does not try to provide:
|
|
46
|
+
|
|
47
|
+
- a fully general host integration layer for every host
|
|
48
|
+
- a full shell parser for `Bash`
|
|
49
|
+
- automatic `git push`
|
|
50
|
+
- a deep upgrader / migration system
|
|
51
|
+
|
|
52
|
+
## What The CLI Does Today
|
|
53
|
+
|
|
54
|
+
### `init`
|
|
55
|
+
|
|
56
|
+
Current responsibilities:
|
|
57
|
+
|
|
58
|
+
- detect project type
|
|
59
|
+
- detect host type
|
|
60
|
+
- generate `harness.yaml`
|
|
61
|
+
- copy task templates into `.harness/tasks/`
|
|
62
|
+
- inject rule blocks into `CLAUDE.md`, `AGENTS.md`, or `GEMINI.md`
|
|
63
|
+
- create minimal runtime directories when not using `--protocol-only`
|
|
64
|
+
|
|
65
|
+
### `task`
|
|
66
|
+
|
|
67
|
+
Current responsibilities:
|
|
68
|
+
|
|
69
|
+
- `task intake`
|
|
70
|
+
- `task confirm`
|
|
71
|
+
- `task suspend-active`
|
|
72
|
+
- create a minimal task draft from natural language
|
|
73
|
+
- close that draft into a confirmed contract
|
|
74
|
+
- provide reusable intake/suspend logic for Codex hooks
|
|
75
|
+
|
|
76
|
+
### `state`
|
|
77
|
+
|
|
78
|
+
Current responsibilities:
|
|
79
|
+
|
|
80
|
+
- `state init`
|
|
81
|
+
- `state get`
|
|
82
|
+
- `state update`
|
|
83
|
+
- `state active`
|
|
84
|
+
- maintain `.harness/state/index.json`
|
|
85
|
+
- maintain `.harness/state/tasks/<task_id>.json`
|
|
86
|
+
|
|
87
|
+
### `verify`
|
|
88
|
+
|
|
89
|
+
Current responsibilities:
|
|
90
|
+
|
|
91
|
+
- read the active task or an explicit `--task-id`
|
|
92
|
+
- evaluate minimal completion requirements
|
|
93
|
+
- return structured JSON
|
|
94
|
+
- distinguish allow vs block via exit code
|
|
95
|
+
|
|
96
|
+
### `report`
|
|
97
|
+
|
|
98
|
+
Current responsibilities:
|
|
99
|
+
|
|
100
|
+
- reuse `verify` before report generation
|
|
101
|
+
- write `.harness/reports/<task_id>.json`
|
|
102
|
+
- move the task to `close / done`
|
|
103
|
+
- validate required output artifacts such as `CHANGELOG.md`, `design note`, and `ADR`
|
|
104
|
+
- compute `delivery_readiness`
|
|
105
|
+
|
|
106
|
+
### `gate`
|
|
107
|
+
|
|
108
|
+
Current responsibilities:
|
|
109
|
+
|
|
110
|
+
- `gate before-tool`
|
|
111
|
+
- deterministic checks for write state legality
|
|
112
|
+
- `protected_paths`
|
|
113
|
+
- path-like scope boundaries
|
|
114
|
+
- high-risk confirmation requirements
|
|
115
|
+
|
|
116
|
+
### `audit`
|
|
117
|
+
|
|
118
|
+
Current responsibilities:
|
|
119
|
+
|
|
120
|
+
- `audit append`
|
|
121
|
+
- `audit read`
|
|
122
|
+
- write `.harness/audit/<task_id>.jsonl`
|
|
123
|
+
- record minimal `gate_violation`
|
|
124
|
+
- expose `force_override` and `manual_confirmation`
|
|
125
|
+
|
|
126
|
+
### `delivery`
|
|
127
|
+
|
|
128
|
+
Current responsibilities:
|
|
129
|
+
|
|
130
|
+
- `delivery ready`
|
|
131
|
+
- `delivery request --action commit|push`
|
|
132
|
+
- `delivery commit`
|
|
133
|
+
- explicit local commit flow
|
|
134
|
+
|
|
135
|
+
Current delivery boundary:
|
|
136
|
+
|
|
137
|
+
- `commit` is supported as an explicit action
|
|
138
|
+
- `push` remains manual
|
|
139
|
+
|
|
140
|
+
### `docs`
|
|
141
|
+
|
|
142
|
+
Current responsibilities:
|
|
143
|
+
|
|
144
|
+
- `docs scaffold --type design-note|adr`
|
|
145
|
+
- generate minimal Markdown skeletons from task context
|
|
146
|
+
|
|
147
|
+
## Codex Support
|
|
148
|
+
|
|
149
|
+
The current repository has the most complete host integration for `Codex`.
|
|
150
|
+
|
|
151
|
+
Current Codex coverage includes:
|
|
152
|
+
|
|
153
|
+
- `SessionStart`
|
|
154
|
+
- `UserPromptSubmit`
|
|
155
|
+
- `PreToolUse`
|
|
156
|
+
- `PostToolUse`
|
|
157
|
+
|
|
158
|
+
Highlights:
|
|
159
|
+
|
|
160
|
+
- automatic intake / continue / clarify
|
|
161
|
+
- pre-tool gating
|
|
162
|
+
- automatic evidence capture
|
|
163
|
+
- active task restore
|
|
164
|
+
|
|
165
|
+
### Current `PreToolUse` Coverage For `Bash`
|
|
166
|
+
|
|
167
|
+
`Bash` currently supports high-confidence path inference for common write commands such as:
|
|
168
|
+
|
|
169
|
+
- `echo ... > file`
|
|
170
|
+
- `cat <<EOF > file`
|
|
171
|
+
- `tee file`
|
|
172
|
+
- `printf ... | tee file`
|
|
173
|
+
- `mkdir -p dir`
|
|
174
|
+
- `touch file`
|
|
175
|
+
- `sed -i file`
|
|
176
|
+
- `perl -pi file`
|
|
177
|
+
- `chmod/chown/chgrp target`
|
|
178
|
+
- `rm file`
|
|
179
|
+
- `truncate -s ... file`
|
|
180
|
+
- `dd ... of=file`
|
|
181
|
+
- `mv src dst`
|
|
182
|
+
- `cp src dst`
|
|
183
|
+
- `install -d dir`
|
|
184
|
+
- `install -D/-m ... dst`
|
|
185
|
+
- `install -Dm644 src dst`
|
|
186
|
+
- `install src dst`
|
|
187
|
+
- `ln -s src dst`
|
|
188
|
+
- `rsync ... dst`
|
|
189
|
+
|
|
190
|
+
If the target path cannot be inferred with high confidence, the CLI degrades conservatively and only applies state-level gating.
|
|
191
|
+
|
|
192
|
+
## Validation Helpers
|
|
193
|
+
|
|
194
|
+
Useful local checks:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
npm --prefix packages/cli run verify:task-core
|
|
198
|
+
npm --prefix packages/cli run verify:codex-e2e
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
From the repository root:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
npm run codex:hooks:check
|
|
205
|
+
npm run codex:e2e
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Local Invocation Note
|
|
209
|
+
|
|
210
|
+
If your current working directory is not the repository root, prefer calling the CLI with an absolute path, for example:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
node /abs/path/to/agent-harness/packages/cli/bin/agent-harness.js status
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Do not assume `node packages/cli/bin/agent-harness.js ...` will work from an arbitrary temporary directory.
|
|
217
|
+
|
|
218
|
+
## Design Constraint
|
|
219
|
+
|
|
220
|
+
- the CLI depends on `@brawnen/agent-harness-protocol`
|
|
221
|
+
- installing `@brawnen/agent-harness-cli` from npm should automatically pull `@brawnen/agent-harness-protocol`
|
|
222
|
+
- the protocol must not depend on the CLI
|
|
223
|
+
- the default npm entrypoint is `npx @brawnen/agent-harness-cli init`
|
|
224
|
+
- this repository currently treats the Node.js CLI as the only mainline implementation
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# @brawnen/agent-harness-cli
|
|
2
|
+
|
|
3
|
+
[English](README.md)
|
|
4
|
+
|
|
5
|
+
这是 `agent-harness` 的 Node.js CLI。
|
|
6
|
+
|
|
7
|
+
当前已完成:
|
|
8
|
+
|
|
9
|
+
- 可执行入口
|
|
10
|
+
- `task` MVP
|
|
11
|
+
- `init` MVP
|
|
12
|
+
- `status` MVP
|
|
13
|
+
- `verify` MVP
|
|
14
|
+
- `state` MVP
|
|
15
|
+
- `report` MVP
|
|
16
|
+
- `gate` MVP
|
|
17
|
+
- `audit` MVP
|
|
18
|
+
- `docs` MVP
|
|
19
|
+
- `--dry-run`
|
|
20
|
+
- `--protocol-only`
|
|
21
|
+
- 宿主规则注入
|
|
22
|
+
- 基础项目配置生成
|
|
23
|
+
- `.codex/hooks.json` 最小方案
|
|
24
|
+
|
|
25
|
+
还未完成:
|
|
26
|
+
|
|
27
|
+
- 更深的宿主集成
|
|
28
|
+
|
|
29
|
+
`init` MVP 当前负责:
|
|
30
|
+
|
|
31
|
+
- 检测项目类型
|
|
32
|
+
- 检测宿主类型
|
|
33
|
+
- 生成 `harness.yaml`
|
|
34
|
+
- 复制协议任务模板到 `.harness/tasks/`
|
|
35
|
+
- 注入 `CLAUDE.md` / `AGENTS.md` / `GEMINI.md` 规则块
|
|
36
|
+
- 在非 `--protocol-only` 模式下生成运行时目录和 Claude Code hooks
|
|
37
|
+
|
|
38
|
+
`task` MVP 当前负责:
|
|
39
|
+
|
|
40
|
+
- `task intake "<任务描述>"`
|
|
41
|
+
- `task confirm`
|
|
42
|
+
- `task suspend-active`
|
|
43
|
+
- 从自然语言生成最小 task draft
|
|
44
|
+
- 将 task draft 闭合为 confirmed contract
|
|
45
|
+
- 在可选 `--suspend-active` 时挂起旧任务
|
|
46
|
+
- 为 Codex hook 提供可复用的 intake / suspend 内核
|
|
47
|
+
|
|
48
|
+
当前不负责:
|
|
49
|
+
|
|
50
|
+
- 完整状态管理迁移
|
|
51
|
+
- 完整 gate / audit / report 迁移
|
|
52
|
+
- 复杂升级与深度 merge
|
|
53
|
+
|
|
54
|
+
`task-core` 当前已经补了最小分类回归样本,可在本地运行:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npm --prefix packages/cli run verify:task-core
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
这组样本当前覆盖:
|
|
61
|
+
|
|
62
|
+
- `matched_continue_keyword`
|
|
63
|
+
- `matched_new_task_keyword`
|
|
64
|
+
- `matched_active_goal_fragment`
|
|
65
|
+
- `matched_active_scope`
|
|
66
|
+
- `ambiguous_high_risk_prompt`
|
|
67
|
+
- `fallback_new_task`
|
|
68
|
+
- `inactive_active_task_state`
|
|
69
|
+
- `no_active_task`
|
|
70
|
+
|
|
71
|
+
`status` MVP 当前负责:
|
|
72
|
+
|
|
73
|
+
- 检查 `harness.yaml`
|
|
74
|
+
- 检查宿主规则块
|
|
75
|
+
- 检查任务模板目录
|
|
76
|
+
- 检查 Claude Code hooks
|
|
77
|
+
- 检查运行时目录与 `.gitignore`
|
|
78
|
+
- 用退出码区分完整、警告和不完整
|
|
79
|
+
|
|
80
|
+
`verify` MVP 当前负责:
|
|
81
|
+
|
|
82
|
+
- 读取 `.harness/state/index.json` 中的 active task,或显式 `--task-id`
|
|
83
|
+
- 读取 `.harness/state/tasks/<task_id>.json`
|
|
84
|
+
- 按最小验证矩阵检查 `intent / evidence / open_questions / acceptance`
|
|
85
|
+
- 输出结构化 JSON 结果
|
|
86
|
+
- 用退出码区分允许完成和阻止完成
|
|
87
|
+
|
|
88
|
+
`state` MVP 当前负责:
|
|
89
|
+
|
|
90
|
+
- `state init`
|
|
91
|
+
- `state get`
|
|
92
|
+
- `state update`
|
|
93
|
+
- `state active`
|
|
94
|
+
- 维护 `.harness/state/index.json`
|
|
95
|
+
- 维护 `.harness/state/tasks/<task_id>.json`
|
|
96
|
+
- 复用最小合法状态迁移表
|
|
97
|
+
|
|
98
|
+
`report` MVP 当前负责:
|
|
99
|
+
|
|
100
|
+
- 读取 active task 或显式 `--task-id`
|
|
101
|
+
- 在生成报告前复用 `verify` 规则做完成门禁检查
|
|
102
|
+
- 写入 `.harness/reports/<task_id>.json`
|
|
103
|
+
- 将任务状态推进到 `close / done`
|
|
104
|
+
- 根据 `output_policy` 校验 `CHANGELOG.md`、`design note`、`ADR` 等交付工件
|
|
105
|
+
- 根据 `delivery_policy` 计算 `commit-ready / push-ready`,并把 `delivery_readiness` 写进报告
|
|
106
|
+
|
|
107
|
+
`report` 额外支持:
|
|
108
|
+
|
|
109
|
+
- `--changelog-file <path>`
|
|
110
|
+
- `--design-note <path>`
|
|
111
|
+
- `--adr <path>`
|
|
112
|
+
|
|
113
|
+
`gate` MVP 当前负责:
|
|
114
|
+
|
|
115
|
+
- `gate before-tool`
|
|
116
|
+
- 基于 active task 或显式 `--task-id` 做确定性门禁判断
|
|
117
|
+
- 检查写入工具的任务状态是否合法
|
|
118
|
+
- 检查 `protected_paths`
|
|
119
|
+
- 检查路径是否越过 path-like scope
|
|
120
|
+
- 在高风险且未确认时返回 `require_confirmation`
|
|
121
|
+
|
|
122
|
+
`audit` MVP 当前负责:
|
|
123
|
+
|
|
124
|
+
- `audit append`
|
|
125
|
+
- `audit read`
|
|
126
|
+
- 写入 `.harness/audit/<task_id>.jsonl`
|
|
127
|
+
- 让 `gate` 记录最小 `gate_violation`
|
|
128
|
+
- 让 `report` 读取 `force_override/manual_confirmation` 作为 `overrides_used`
|
|
129
|
+
|
|
130
|
+
`delivery_policy` 第一版当前负责:
|
|
131
|
+
|
|
132
|
+
- 在 `status` 中展示 active task 的 `commit-ready / push-ready`
|
|
133
|
+
- 在 `report` 中输出 `delivery_readiness`
|
|
134
|
+
- 提供 `delivery ready`、`delivery request --action commit|push` 和 `delivery commit` 入口
|
|
135
|
+
- `commit` 保留为 skill 化的显式动作
|
|
136
|
+
- `push` 保留为人工动作,不作为 skill 默认能力
|
|
137
|
+
- 当前只做 readiness 计算,不会自动执行 `git commit` 或 `git push`
|
|
138
|
+
- `commit_exists` 会基于任务报告中的 `actual_scope + output_artifacts` 检查相关文件是否仍有未提交改动
|
|
139
|
+
- 若任务相关文件已经干净,则视为该任务已完成本地 `commit`
|
|
140
|
+
|
|
141
|
+
`delivery commit` 当前行为:
|
|
142
|
+
|
|
143
|
+
- 先复用 `delivery request --action commit`
|
|
144
|
+
- 读取任务报告中的 `actual_scope` 和 `output_artifacts`
|
|
145
|
+
- 目录型 scope 只会展开为当前有变更的文件
|
|
146
|
+
- 支持 `--dry-run` 先预览提交计划
|
|
147
|
+
- 对明显过宽的目录 scope 默认阻断,需显式使用 `--force-wide-scope`
|
|
148
|
+
- 自动执行本地 `git add` / `git commit`
|
|
149
|
+
- 永远不会执行 `git push`
|
|
150
|
+
|
|
151
|
+
`docs scaffold` 当前行为:
|
|
152
|
+
|
|
153
|
+
- 提供 `docs scaffold --type design-note|adr`
|
|
154
|
+
- 默认读取 active task,也支持 `--task-id`
|
|
155
|
+
- 根据任务上下文生成最小 Markdown 骨架
|
|
156
|
+
- 默认写入 `output_policy.design_note.directory` 或 `output_policy.adr.directory`
|
|
157
|
+
- 支持 `--path` 自定义目标路径
|
|
158
|
+
- 已存在文件默认阻止覆盖,需显式使用 `--force`
|
|
159
|
+
|
|
160
|
+
当 `report` 因缺少 `design_note` 或 `adr` 被阻断时:
|
|
161
|
+
|
|
162
|
+
- 会直接输出对应的 `docs scaffold` 建议命令
|
|
163
|
+
- 并给出重新执行 `report` 时应补的 `--design-note` / `--adr` 参数
|
|
164
|
+
|
|
165
|
+
`status` 当前也会对 active task 主动给出 output artifact 提示:
|
|
166
|
+
|
|
167
|
+
- 若当前任务要求 `changelog / design_note / adr`
|
|
168
|
+
- 会直接提示建议补齐的工件
|
|
169
|
+
- 对 `design_note / adr` 会给出可直接执行的 `docs scaffold` 命令
|
|
170
|
+
|
|
171
|
+
Codex 自动 evidence:
|
|
172
|
+
|
|
173
|
+
- 当前仓库在 `Codex` 下已为 `Bash` 接入 `PostToolUse`
|
|
174
|
+
- 常见 Bash 命令结果会自动追加到 active task 的 `evidence`
|
|
175
|
+
- 若命令明显属于测试,或任务当前处于 `verify` 阶段,则会优先记录为 `test_result`
|
|
176
|
+
- 在高风险任务上,`UserPromptSubmit` 会把显式确认语句自动记录为 `manual_confirmation`
|
|
177
|
+
- `别问了直接做`、`跳过验证` 这类显式 override 语句会自动记录为 `force_override`
|
|
178
|
+
|
|
179
|
+
Codex `PreToolUse` 当前行为:
|
|
180
|
+
|
|
181
|
+
- 会在 `Write / Edit / NotebookEdit / Bash` 前调用 `gate before-tool`
|
|
182
|
+
- `needs_clarification / draft / blocked / failed / done / suspended` 状态下的写入会被前置阻断
|
|
183
|
+
- 会结合 task state 与 `harness.yaml risk_rules.path_matches` 动态判断高风险写入
|
|
184
|
+
- 高风险写入且未确认时,会在工具执行前阻断并要求先确认
|
|
185
|
+
- `Bash` 当前已支持最小高置信路径提取,例如:
|
|
186
|
+
- `echo ... > file`
|
|
187
|
+
- `cat <<EOF > file`
|
|
188
|
+
- `tee file`
|
|
189
|
+
- `printf ... | tee file`
|
|
190
|
+
- `mkdir -p dir`
|
|
191
|
+
- `touch file`
|
|
192
|
+
- `sed -i file`
|
|
193
|
+
- `perl -pi file`
|
|
194
|
+
- `chmod/chown/chgrp target`
|
|
195
|
+
- `rm file`
|
|
196
|
+
- `truncate -s ... file`
|
|
197
|
+
- `dd ... of=file`
|
|
198
|
+
- `mv src dst`
|
|
199
|
+
- `cp src dst`
|
|
200
|
+
- `install -d dir`
|
|
201
|
+
- `install -D/-m ... dst`
|
|
202
|
+
- `install -Dm644 src dst`
|
|
203
|
+
- `install src dst`
|
|
204
|
+
- `ln -s src dst`
|
|
205
|
+
- `rsync ... dst`
|
|
206
|
+
- 无法高置信提取目标路径时,会保守降级为仅做状态级门禁
|
|
207
|
+
|
|
208
|
+
本地验证提示:
|
|
209
|
+
|
|
210
|
+
- 如果当前工作目录不是仓库根目录,调用 CLI 时应使用绝对路径,例如:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
node /abs/path/to/agent-harness/packages/cli/bin/agent-harness.js audit read --task-id <task-id>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
- 不要在临时目录里直接运行相对路径 `node packages/cli/bin/agent-harness.js ...`,否则容易把路径错误误判成命令读取异常
|
|
217
|
+
|
|
218
|
+
Codex E2E 回归:
|
|
219
|
+
|
|
220
|
+
- 可执行 `npm --prefix packages/cli run verify:codex-e2e`
|
|
221
|
+
- 或在仓库根目录执行 `npm run codex:e2e`
|
|
222
|
+
- 当前最小回归覆盖:新任务自动 intake、follow-up 不误切、高风险确认链路、hook 降级提示
|
|
223
|
+
- 当前回归采用“真实 `codex exec` smoke + hook 主链路回归”混合方式,优先验证我们自己的接入链路
|
|
224
|
+
- 当前脚本会在**当前 trusted 仓库**里执行真实 Codex 回归,并清理自己创建的 task/audit/report 文件
|
|
225
|
+
- 运行前要求当前仓库没有 active task
|
|
226
|
+
|
|
227
|
+
设计约束:
|
|
228
|
+
|
|
229
|
+
- CLI 依赖 `@brawnen/agent-harness-protocol`
|
|
230
|
+
- 从 npm 安装 `@brawnen/agent-harness-cli` 时,应自动带上 `@brawnen/agent-harness-protocol`
|
|
231
|
+
- 默认 npm 入口是 `npx @brawnen/agent-harness-cli init`
|
|
232
|
+
- 当前仓库以 Node.js CLI 作为唯一主线实现
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@brawnen/agent-harness-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI for task convergence, verification, reporting, and delivery in agent-harness projects.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"bin": {
|
|
7
|
+
"agent-harness": "./bin/agent-harness.js"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"files": [
|
|
11
|
+
"bin",
|
|
12
|
+
"src",
|
|
13
|
+
"LICENSE",
|
|
14
|
+
"README.md",
|
|
15
|
+
"README.zh-CN.md"
|
|
16
|
+
],
|
|
17
|
+
"keywords": [
|
|
18
|
+
"agent",
|
|
19
|
+
"ai",
|
|
20
|
+
"workflow",
|
|
21
|
+
"task",
|
|
22
|
+
"codex",
|
|
23
|
+
"cli"
|
|
24
|
+
],
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/brawnen/agent-harness.git",
|
|
28
|
+
"directory": "packages/cli"
|
|
29
|
+
},
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/brawnen/agent-harness/issues"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/brawnen/agent-harness/tree/main/packages/cli",
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@brawnen/agent-harness-protocol": "^0.1.0"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"start": "node ./bin/agent-harness.js --help"
|
|
42
|
+
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=18"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { appendAuditEntry, readAuditEntries } from "../lib/audit-store.js";
|
|
2
|
+
|
|
3
|
+
export function runAudit(argv) {
|
|
4
|
+
const [subcommand, ...rest] = argv;
|
|
5
|
+
|
|
6
|
+
if (subcommand === "append") {
|
|
7
|
+
return runAuditAppend(rest);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (subcommand === "read") {
|
|
11
|
+
return runAuditRead(rest);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
console.error("audit 可用子命令: append, read");
|
|
15
|
+
return 1;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function runAuditAppend(argv) {
|
|
19
|
+
const parsed = parseAppendArgs(argv);
|
|
20
|
+
if (!parsed.ok) {
|
|
21
|
+
console.error(parsed.error);
|
|
22
|
+
return 1;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const entry = appendAuditEntry(process.cwd(), parsed.options);
|
|
27
|
+
printJson(entry);
|
|
28
|
+
return 0;
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.error(error.message);
|
|
31
|
+
return 1;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function runAuditRead(argv) {
|
|
36
|
+
const parsed = parseReadArgs(argv);
|
|
37
|
+
if (!parsed.ok) {
|
|
38
|
+
console.error(parsed.error);
|
|
39
|
+
return 1;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const entries = readAuditEntries(process.cwd(), parsed.options.taskId);
|
|
44
|
+
printJson({
|
|
45
|
+
schema_version: "0.3",
|
|
46
|
+
entries
|
|
47
|
+
});
|
|
48
|
+
return 0;
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error(error.message);
|
|
51
|
+
return 1;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function parseAppendArgs(argv) {
|
|
56
|
+
const options = {
|
|
57
|
+
description: null,
|
|
58
|
+
event_type: null,
|
|
59
|
+
phase: null,
|
|
60
|
+
risk_at_time: "unknown",
|
|
61
|
+
signal: null,
|
|
62
|
+
task_id: null,
|
|
63
|
+
user_input: null
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
67
|
+
const arg = argv[index];
|
|
68
|
+
if (Object.hasOwn(FLAG_MAP, arg)) {
|
|
69
|
+
const key = FLAG_MAP[arg];
|
|
70
|
+
options[key] = argv[index + 1] ?? null;
|
|
71
|
+
index += 1;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return { ok: false, error: `未知参数: ${arg}` };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!options.task_id || !options.event_type || !options.phase || !options.signal || !options.description) {
|
|
79
|
+
return { ok: false, error: "需要 --task-id --event-type --phase --signal --description 参数" };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return { ok: true, options };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function parseReadArgs(argv) {
|
|
86
|
+
const taskIdFlagIndex = argv.indexOf("--task-id");
|
|
87
|
+
if (taskIdFlagIndex < 0 || !argv[taskIdFlagIndex + 1]) {
|
|
88
|
+
return { ok: false, error: "需要 --task-id 参数" };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (argv.length !== 2) {
|
|
92
|
+
return { ok: false, error: "audit read 仅支持 --task-id <id>" };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return { ok: true, options: { taskId: argv[taskIdFlagIndex + 1] } };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function printJson(value) {
|
|
99
|
+
console.log(`${JSON.stringify(value, null, 2)}\n`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const FLAG_MAP = {
|
|
103
|
+
"--description": "description",
|
|
104
|
+
"--event-type": "event_type",
|
|
105
|
+
"--phase": "phase",
|
|
106
|
+
"--risk-at-time": "risk_at_time",
|
|
107
|
+
"--signal": "signal",
|
|
108
|
+
"--task-id": "task_id",
|
|
109
|
+
"--user-input": "user_input"
|
|
110
|
+
};
|