svharness 0.8.0 → 0.11.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/README.md +267 -31
- package/dist/adapters/claude-code.js +1 -0
- package/dist/adapters/codechat.js +1 -0
- package/dist/adapters/cursor.js +1 -0
- package/dist/adapters/generic.js +1 -0
- package/dist/adapters/index.js +2 -0
- package/dist/adapters/opencode.js +17 -0
- package/dist/adapters/qoder.js +1 -0
- package/dist/commands/apply.js +48 -3
- package/dist/commands/convert.js +369 -0
- package/dist/commands/init.js +125 -8
- package/dist/commands/references-apply-skills.js +47 -0
- package/dist/commands/wizard.js +441 -0
- package/dist/config/constants.js +7 -0
- package/dist/config/index.js +18 -0
- package/dist/config/load-config.js +54 -0
- package/dist/config/merge-options.js +115 -0
- package/dist/config/normalize.js +165 -0
- package/dist/config/save-config.js +40 -0
- package/dist/config/types.js +2 -0
- package/dist/core/agent-injector.js +58 -9
- package/dist/core/apply-project-entry.js +92 -0
- package/dist/core/build-project-entry.js +98 -0
- package/dist/core/doc-intake-paths.js +155 -0
- package/dist/core/extra-assets-intake.js +254 -0
- package/dist/core/markitdown-client.js +156 -0
- package/dist/core/next-steps.js +33 -22
- package/dist/core/reference-apply-skills.js +35 -0
- package/dist/core/render-meta.js +2 -1
- package/dist/core/repomix-pack.js +3 -3
- package/dist/core/state.js +44 -24
- package/dist/index.js +207 -132
- package/dist/utils/validate-args.js +100 -0
- package/dist/wiki/wikiTasksWriter.js +5 -6
- package/package.json +2 -1
- package/templates/_shared/apply-skills/harness-apply-skills-main.md +45 -14
- package/templates/_shared/build-rules/harness-build-rule-agent-agnostic.md +5 -5
- package/templates/_shared/build-rules/harness-build-rule-chinese-only.md +5 -5
- package/templates/_shared/build-rules/harness-build-rule-convert-check.md +46 -0
- package/templates/_shared/build-rules/harness-build-rule-memory-write.md +1 -1
- package/templates/_shared/build-rules/harness-build-rule-orchestrator-flow.md +36 -10
- package/templates/_shared/build-rules/harness-build-rule-skills-tasks-output.md +3 -2
- package/templates/_shared/build-rules/harness-build-rule-specs-schema.md +3 -3
- package/templates/_shared/build-rules/harness-build-rule-user-interaction.md +36 -16
- package/templates/_shared/build-skills/harness-build-skill-agent-env-merge.md +75 -0
- package/templates/_shared/build-skills/harness-build-skill-knowledge-builder.md +49 -85
- package/templates/_shared/build-skills/harness-build-skill-orchestrator.md +35 -18
- package/templates/_shared/build-skills/harness-build-skill-references-intake.md +91 -0
- package/templates/_shared/build-skills/harness-build-skill-spec-builder.md +19 -9
- package/templates/_shared/build-skills/harness-build-skill-wiki-writer.md +24 -24
- package/templates/_shared/build-skills/harness-build-skills-main.md +83 -0
- package/templates/_shared/meta/AGENTS_APPLY.md.ejs +139 -0
- package/templates/_shared/meta/{AGENTS.md.ejs → AGENTS_BUILD.md.ejs} +7 -5
- package/templates/_shared/meta/CHANGELOG.md.ejs +3 -3
- package/templates/_shared/meta/README.md.ejs +11 -9
- package/templates/_shared/meta/harness.yaml.ejs +28 -7
- package/templates/_shared/skeleton/baseline/code/.gitkeep +1 -0
- package/templates/_shared/skeleton/baseline/wiki/.gitkeep +1 -0
- package/templates/_shared/skeleton/references/apply-skills-registry.example.yaml +11 -0
- package/templates/_shared/skeleton/references/md/.gitkeep +1 -0
- package/templates/_shared/skeleton/references/raw/.gitkeep +1 -0
- package/templates/_shared/skeleton/references/yaml/.gitkeep +1 -0
- package/templates/_shared/skeleton/requirements/md/.gitkeep +1 -0
- package/templates/_shared/skeleton/requirements/raw/.gitkeep +1 -0
- package/templates/_shared/skeleton/requirements/yaml/.gitkeep +1 -0
- package/templates/android-xml/skeleton/agent-env/skills/harness-android-cli/SKILL.md +88 -0
- package/templates/android-xml/skeleton/agent-env/skills/harness-android-service-patterns/SKILL.md +205 -0
- package/templates/android-xml/skeleton/agent-env/skills/harness-android-xml-architecture/SKILL.md +138 -0
- package/templates/android-xml/skeleton/agent-env/skills/harness-lifecycle-management/SKILL.md +158 -0
- package/templates/android-xml/skeleton/agent-env/skills/harness-xml-ui/SKILL.md +112 -0
- package/templates/cpp/skeleton/agent-env/skills/harness-cmake-build/SKILL.md +163 -0
- package/templates/cpp/skeleton/agent-env/skills/harness-cpp-architecture/SKILL.md +157 -0
- package/templates/cpp/skeleton/agent-env/skills/harness-cpp-concurrency/SKILL.md +180 -0
- package/templates/cpp/skeleton/agent-env/skills/harness-memory-safety/SKILL.md +163 -0
- package/templates/cpp/skeleton/agent-env/skills/harness-modern-cpp/SKILL.md +149 -0
- package/templates/python/skeleton/agent-env/skills/harness-async-patterns/SKILL.md +162 -0
- package/templates/python/skeleton/agent-env/skills/harness-python-architecture/SKILL.md +160 -0
- package/templates/python/skeleton/agent-env/skills/harness-python-package-structure/SKILL.md +210 -0
- package/templates/python/skeleton/agent-env/skills/harness-python-performance/SKILL.md +207 -0
- package/templates/python/skeleton/agent-env/skills/harness-python-testing/SKILL.md +198 -0
- package/templates/svharness.config.example.yaml +39 -0
- package/templates/web-react/skeleton/agent-env/skills/harness-react-architecture/SKILL.md +177 -0
- package/templates/web-react/skeleton/agent-env/skills/harness-react-performance/SKILL.md +177 -0
- package/templates/web-react/skeleton/agent-env/skills/harness-react-testing/SKILL.md +193 -0
- package/templates/web-react/skeleton/agent-env/skills/harness-react-ui-patterns/SKILL.md +257 -0
- package/templates/web-react/skeleton/agent-env/skills/harness-state-management/SKILL.md +189 -0
- package/templates/_shared/skeleton/assets/baseline/code/.gitkeep +0 -1
- package/templates/_shared/skeleton/assets/baseline/wiki/.gitkeep +0 -1
- package/templates/_shared/skeleton/assets/raw/.gitkeep +0 -1
- package/templates/_shared/skeleton/assets/requirements/.gitkeep +0 -1
- /package/templates/_shared/skeleton/{assets/baseline/repomix → agent-env/_incoming/skills}/.gitkeep +0 -0
package/README.md
CHANGED
|
@@ -29,6 +29,12 @@ cd svharnessbuild && npm install && npm run build && npm link
|
|
|
29
29
|
# 最简 —— 只填名字,其余取默认(arch=android-compose, agent=codechat)
|
|
30
30
|
svharness build --harness-name my-app
|
|
31
31
|
|
|
32
|
+
# 交互式向导(推荐新手)—— 可填路径 + 文字说明,保存配置或立即执行
|
|
33
|
+
svharness wizard
|
|
34
|
+
|
|
35
|
+
# 配置文件驱动(团队模板 / CI)
|
|
36
|
+
svharness build --config svharness.config.yaml --yes
|
|
37
|
+
|
|
32
38
|
# 一行式 —— 跳过交互,直接生成
|
|
33
39
|
svharness build --harness-name my-app --arch android-compose --agent qoder --yes
|
|
34
40
|
|
|
@@ -36,10 +42,38 @@ svharness build --harness-name my-app --arch android-compose --agent qoder --yes
|
|
|
36
42
|
svharness apply --harness ./my-app-harness --target ../other-project --yes
|
|
37
43
|
```
|
|
38
44
|
|
|
45
|
+
### 配置文件与向导(v0.10+)
|
|
46
|
+
|
|
47
|
+
**优先级**:`CLI 参数 > svharness.config.yaml > 代码默认值`
|
|
48
|
+
|
|
49
|
+
1. 复制示例配置:`templates/svharness.config.example.yaml` → 项目根 `svharness.config.yaml`
|
|
50
|
+
2. 编辑 `build` / `apply` / `convert` 各节参数
|
|
51
|
+
3. 执行:`svharness build --yes`(自动读取当前目录下的 `svharness.config.yaml`)
|
|
52
|
+
|
|
53
|
+
也可显式指定:`svharness build --config ./team/android-compose.yaml --yes`
|
|
54
|
+
|
|
55
|
+
`build` 成功后落盘当前参数:`svharness build --harness-name my-app --save-config`
|
|
56
|
+
|
|
57
|
+
**`svharness wizard`**:分步 TUI,支持同时填写**文件路径**与**说明文字**(如 `requirementsNote`),结束时可选「立即执行 / 仅保存配置 / 保存并执行」。
|
|
58
|
+
|
|
39
59
|
生成完成后,在你的 Agent IDE 中说:
|
|
40
|
-
- "运行 harness-build-skill-orchestrator"即可开始逐步填充内容;
|
|
60
|
+
- "运行 harness-build-skills-main"或"harness-build-skill-orchestrator"即可开始逐步填充内容;
|
|
41
61
|
- 构建完成后在目标项目中说"应用 harness-apply-skills-main 完成 xxx 功能开发"即可调用 harness。
|
|
42
62
|
|
|
63
|
+
### 演示数据集(demo_project)
|
|
64
|
+
|
|
65
|
+
仓库自带 **[`demo_project/`](./demo_project/)**(Python 计算器主题),可一次性验证 `--baseline` / `--requirements` / `--references` / `--extra-skills` 四类输入及 intake 分类。详见 [`demo_project/README.md`](./demo_project/README.md)。
|
|
66
|
+
|
|
67
|
+
```powershell
|
|
68
|
+
cd svharnessbuild
|
|
69
|
+
svharness build --harness-name demo-py --arch python --agent codechat `
|
|
70
|
+
--baseline ./demo_project/baseline `
|
|
71
|
+
--requirements ./demo_project/requirements `
|
|
72
|
+
--references ./demo_project/references `
|
|
73
|
+
--extra-skills ./demo_project/extra-skills `
|
|
74
|
+
--yes --force
|
|
75
|
+
```
|
|
76
|
+
|
|
43
77
|
---
|
|
44
78
|
|
|
45
79
|
## 核心概念
|
|
@@ -51,7 +85,7 @@ Harness 是一个 **项目本地的知识层**,由两大部分组成:
|
|
|
51
85
|
| 部分 | 位置 | 生命周期 | 说明 |
|
|
52
86
|
|------|------|----------|------|
|
|
53
87
|
| **Agent 注入目录** | `.qoder/` / `.codechat/` / `.cursor/` 等 | `build` 时创建,Agent 自动加载 | rules + build-skills |
|
|
54
|
-
| **Harness 目录** | `<harness-name>-harness/` | `build` 创建骨架 → Agent 逐步填充 | specs /
|
|
88
|
+
| **Harness 目录** | `<harness-name>-harness/` | `build` 创建骨架 → Agent 逐步填充 | specs / requirements / references / baseline / agent-env / tasks |
|
|
55
89
|
|
|
56
90
|
### 目录结构
|
|
57
91
|
|
|
@@ -60,11 +94,11 @@ Harness 是一个 **项目本地的知识层**,由两大部分组成:
|
|
|
60
94
|
```
|
|
61
95
|
<harness-name>-harness/
|
|
62
96
|
├── harness.yaml # 入口清单(架构 / agent / schema 引用)
|
|
63
|
-
├──
|
|
97
|
+
├── AGENTS_BUILD.md # 面向 Agent 的使用指南
|
|
64
98
|
├── README.md # 面向人的项目概览
|
|
65
99
|
├── VERSION
|
|
66
100
|
├── CHANGELOG.md
|
|
67
|
-
├── .harness-build-state.yaml # 构建进度追踪(
|
|
101
|
+
├── .harness-build-state.yaml # 构建进度追踪(S10 … S90)
|
|
68
102
|
│
|
|
69
103
|
├── specs/ # 契约层
|
|
70
104
|
│ ├── signals/schema.json
|
|
@@ -72,12 +106,17 @@ Harness 是一个 **项目本地的知识层**,由两大部分组成:
|
|
|
72
106
|
│ ├── behavior/schema.json
|
|
73
107
|
│ └── interfaces/schema.json
|
|
74
108
|
│
|
|
75
|
-
├──
|
|
76
|
-
│ ├── raw/
|
|
77
|
-
│ ├──
|
|
78
|
-
│ └──
|
|
79
|
-
|
|
80
|
-
│
|
|
109
|
+
├── requirements/ # 正式需求(参与条目化)
|
|
110
|
+
│ ├── raw/ # S20_collect_inputs 用户入口
|
|
111
|
+
│ ├── md/ # convert 产物
|
|
112
|
+
│ └── yaml/ # S40 条目化产出
|
|
113
|
+
├── references/ # 参考资料(不参与条目化)
|
|
114
|
+
│ ├── raw/
|
|
115
|
+
│ ├── md/
|
|
116
|
+
│ └── yaml/
|
|
117
|
+
└── baseline/
|
|
118
|
+
├── code/ # 参考代码快照
|
|
119
|
+
└── wiki/ # 架构 wiki
|
|
81
120
|
│
|
|
82
121
|
├── agent-env/ # Agent 运行期环境
|
|
83
122
|
│ ├── rules/ # 编码规则(.mdc,always_on 加载)
|
|
@@ -89,15 +128,31 @@ Harness 是一个 **项目本地的知识层**,由两大部分组成:
|
|
|
89
128
|
└── tasks/ # 可复用的开发者工作流
|
|
90
129
|
```
|
|
91
130
|
|
|
92
|
-
同时,CLI
|
|
131
|
+
同时,CLI 会在**项目根**写入 `CLAUDE.md`(`--agent codechat` 或 `claude-code`)或 `AGENTS.md`(`qoder` / `cursor` / `opencode` / `generic`),并向 Agent IDE 的 skill 目录注入 **7 个构建辅助 skill**:
|
|
93
132
|
|
|
94
133
|
| Skill | 职责 |
|
|
95
134
|
|-------|------|
|
|
135
|
+
| `harness-build-skills-main` | **总清单**:解析内联绑定元数据 → 装载构建规则 → 路由到各子 skill |
|
|
96
136
|
| `harness-build-skill-orchestrator` | 读取构建状态,路由到下一阶段 |
|
|
97
137
|
| `harness-build-skill-spec-builder` | raw → requirements → specs 管线 |
|
|
98
|
-
| `harness-build-skill-
|
|
138
|
+
| `harness-build-skill-references-intake` | S60 references 转换 + 结构化索引 |
|
|
139
|
+
| `harness-build-skill-agent-env-merge` | S61 baseline 自动提取确认 + S65 合并写入 |
|
|
140
|
+
| `harness-build-skill-knowledge-builder` | S10 baseline 样本 + S70 skills/tasks 索引 |
|
|
99
141
|
| `harness-build-skill-wiki-writer` | 按 TASKS.md 逐页撰写 wiki 正文 |
|
|
100
142
|
|
|
143
|
+
简短阶段对照(阶段 → skill):
|
|
144
|
+
|
|
145
|
+
```text
|
|
146
|
+
S10_wiki -> harness-build-skill-wiki-writer(正文)/ harness-build-skill-knowledge-builder(样本子任务)
|
|
147
|
+
S20_collect_inputs -> harness-build-skill-orchestrator
|
|
148
|
+
S30_convert_docs -> harness-build-skill-orchestrator
|
|
149
|
+
S40/S50 -> harness-build-skill-spec-builder
|
|
150
|
+
S60 -> harness-build-skill-references-intake
|
|
151
|
+
S61/S65 -> harness-build-skill-agent-env-merge
|
|
152
|
+
S70 -> harness-build-skill-knowledge-builder
|
|
153
|
+
S80/S90 -> harness-build-skill-orchestrator
|
|
154
|
+
```
|
|
155
|
+
|
|
101
156
|
`.harness-build-state.yaml` 跟踪进度,任何阶段可中断再续。
|
|
102
157
|
|
|
103
158
|
#### 构建辅助 skill / rule 命名规范
|
|
@@ -112,7 +167,7 @@ harness-build-{skill|rule}-<semantic-name>
|
|
|
112
167
|
|
|
113
168
|
| 资源类型 | 目录 | 命名模式 | 现有成员 |
|
|
114
169
|
|----------|------|----------|----------|
|
|
115
|
-
| **Build skill** | `templates/_shared/build-skills/` | `harness-build-skill-<name>.md` | `orchestrator` / `spec-builder` / `knowledge-builder` / `wiki-writer` |
|
|
170
|
+
| **Build skill** | `templates/_shared/build-skills/` | `harness-build-skill-<name>.md` | `skills-main` / `orchestrator` / `spec-builder` / `references-intake` / `agent-env-merge` / `knowledge-builder` / `wiki-writer` |
|
|
116
171
|
| **Build rule** | `templates/_shared/build-rules/` | `harness-build-rule-<name>.md` | `agent-agnostic` / `chinese-only` / `memory-write` / `orchestrator-flow` / `skills-tasks-output` / `specs-schema` / `user-interaction` |
|
|
117
172
|
|
|
118
173
|
约束:
|
|
@@ -127,26 +182,60 @@ harness-build-{skill|rule}-<semantic-name>
|
|
|
127
182
|
|
|
128
183
|
| 阶段 | 动作 | 产物 |
|
|
129
184
|
|------|------|------|
|
|
130
|
-
| **
|
|
131
|
-
| **
|
|
132
|
-
| **
|
|
133
|
-
| **
|
|
134
|
-
| **
|
|
135
|
-
| **
|
|
136
|
-
| **
|
|
137
|
-
| **
|
|
185
|
+
| **S10_wiki** | 构建 baseline wiki(仅当有 baseline 时出现,项目经验底座) | `baseline/wiki/` |
|
|
186
|
+
| **S20_collect_inputs** | 添加相关文件:需求/参考文档 + 额外运行期资源征询(`--extra-skills` 单入口,可混放 skills/rules) | `requirements/raw/` + `references/raw/` + `agent-env/_incoming/skills/` |
|
|
187
|
+
| **S30_convert_docs** | 非 Markdown 原始文档转 Markdown | `requirements/md/` + `references/md/` |
|
|
188
|
+
| **S40_extract_requirements** | 条目化需求 | `requirements/yaml/*.yaml` |
|
|
189
|
+
| **S50_generate_specs** | 生成规格 | `specs/<layer>/<module>.<layer>.yaml` + schema 校验 |
|
|
190
|
+
| **S60_process_references** | references 处理(`svharness convert` + 结构化索引 + 用户确认落地) | `references/md/` |
|
|
191
|
+
| **S61_confirm_baseline_extraction** | 确认是否自动从 baseline 提取 skills/rules(表单确认) | `.harness-build-state.yaml`(`phases.S61_confirm_baseline_extraction.baseline_auto_extract`) |
|
|
192
|
+
| **S65_customize_agent_env** | agent-env 定制(extra-skills/extra-rules 冲突建议与重命名建议 → 用户确认 → 写入) | `agent-env/rules/` + `agent-env/skills/` |
|
|
193
|
+
| **S70_runtime_assets** | 运行期 Skills & tasks 索引(skill 执行 task) | `agent-env/skills/` + `tasks/templates/` |
|
|
194
|
+
| **S80_seed_memory** | Memory 初始化 | `agent-env/memory/categories/` |
|
|
195
|
+
| **S90_finalize** | 封板 | 版本 bump + CHANGELOG + 终审 |
|
|
138
196
|
|
|
139
197
|
> 反复调用 orchestrator 总是从"第一个非 DONE 的阶段"继续。
|
|
140
|
-
> **
|
|
141
|
-
> **
|
|
198
|
+
> **S10_wiki 仅在有 baseline 时出现;无 baseline 则不构建 wiki,流程从 S20_collect_inputs 开始。**
|
|
199
|
+
> **S20_collect_inputs 必须等待用户放入需求文档,且需显式征询 references 与额外运行期资源输入(`--extra-skills`,可混放 skills/rules);Agent 不得自行生成占位文件。若 build 传入了 `--requirements/--references`,CLI 会在拷贝到 raw 后自动尝试 convert 到 md。**
|
|
200
|
+
> **S60_process_references 专注 references:必须执行 `svharness convert`,并产出结构化索引(规制约束 / skills 候选 / signals / manuals),经表单确认后再进入后续阶段。**
|
|
201
|
+
> **S61_confirm_baseline_extraction 必须显式确认是否启用 baseline 自动提取 skills/rules;未经确认不得在 S65 自动提取。**
|
|
202
|
+
> **S65_customize_agent_env 专注 extra-skills/extra-rules:来源可来自 `--extra-skills` 导入后的 `_incoming/manifest.yaml`,先冲突识别与重命名建议,再表单确认写入;推荐命名:`harness-apply-skills-<topic>` 与 `harness-apply-rules-<topic>.md/.mdc`。**
|
|
142
203
|
|
|
143
204
|
---
|
|
144
205
|
|
|
145
206
|
## 命令参考
|
|
146
207
|
|
|
208
|
+
### `wizard` —— 交互式向导(v0.10+)
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
svharness wizard
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
分步选择 `build` / `apply` / `convert`,填写路径与可选说明,最后保存到 `svharness.config.yaml` 和/或立即执行对应命令。
|
|
215
|
+
|
|
216
|
+
### 配置文件 `svharness.config.yaml`(v0.10+)
|
|
217
|
+
|
|
218
|
+
| 顶层字段 | 说明 |
|
|
219
|
+
|----------|------|
|
|
220
|
+
| `version` | 固定为 `1` |
|
|
221
|
+
| `defaults` | 各命令共享默认(`arch` / `agent` / `yes` 等) |
|
|
222
|
+
| `build` | 对应 `svharness build` |
|
|
223
|
+
| `apply` | 对应 `svharness apply` |
|
|
224
|
+
| `convert` | 对应 `svharness convert` |
|
|
225
|
+
|
|
226
|
+
`build` 节除路径外,可写人类可读说明(仅写入配置文件,供团队阅读):
|
|
227
|
+
|
|
228
|
+
| 字段 | 说明 |
|
|
229
|
+
|------|------|
|
|
230
|
+
| `requirementsNote` | 需求文档业务说明 |
|
|
231
|
+
| `referencesNote` | 参考资料说明 |
|
|
232
|
+
| `extraSkillsNote` | 额外 skills/rules 说明 |
|
|
233
|
+
|
|
234
|
+
完整示例见 [`templates/svharness.config.example.yaml`](templates/svharness.config.example.yaml)。
|
|
235
|
+
|
|
147
236
|
### `build` —— 构建 harness(v0.8 起的主命令)
|
|
148
237
|
|
|
149
|
-
> 旧名 `svharness init`(以及 `
|
|
238
|
+
> 旧名 `svharness init`(以及 `svharness build`)作为兼容别名保留,调用时会打印 deprecation 警告。
|
|
150
239
|
|
|
151
240
|
#### 交互式
|
|
152
241
|
|
|
@@ -170,14 +259,24 @@ svharness build \
|
|
|
170
259
|
|
|
171
260
|
| 参数 | 是否必填 | 说明 | 默认值 |
|
|
172
261
|
|------|----------|------|--------|
|
|
173
|
-
| `--
|
|
262
|
+
| `--config <path>` | 可选 | 读取 YAML/JSON 配置;省略时在 cwd 查找 `svharness.config.yaml` | — |
|
|
263
|
+
| `--save-config [path]` | 可选 | build 成功后把参数写入配置文件 | — |
|
|
264
|
+
| `--harness-name <name>` | ✅ 必填* | harness 名称;可在 `build.harnessName` 中提供 | — |
|
|
174
265
|
| `--name <name>` | ⚠️ 已废弃别名 | 等同 `--harness-name`,下个 minor 版本移除 | — |
|
|
175
266
|
| `--arch <arch>` | 可选 | 架构模板:`android-compose` / `android-xml` / `cpp` / `web-react` / `python` | `android-compose` |
|
|
176
|
-
| `--agent <agent>` | 可选 | 目标 Agent IDE:`codechat` / `qoder` / `cursor` / `claude-code` / `generic` | `codechat` |
|
|
267
|
+
| `--agent <agent>` | 可选 | 目标 Agent IDE:`codechat` / `qoder` / `cursor` / `claude-code` / `opencode` / `generic` | `codechat` |
|
|
177
268
|
| `--baseline <path\|url>` | 可选 | 基线来源:本地目录 **或** git 仓库 URL | — |
|
|
269
|
+
| `--requirements <path>` | 可选 | 需求输入路径(文件或目录);build 阶段**扁平**拷贝到 `requirements/raw/`(不保留源目录里的 `assets/raw/converted_md` 等嵌套),随后自动 convert 到 `requirements/md/`(失败仅告警,不中断 build) | — |
|
|
270
|
+
| `--references <path>` | 可选 | 参考资料输入路径(文件或目录);build 阶段**扁平**拷贝到 `references/raw/`,随后自动 convert 到 `references/md/`(失败仅告警,不中断 build) | — |
|
|
271
|
+
| `--extra-skills <path...>` | 可选 | 额外运行期资源输入(文件/目录/glob,可混放 skills/rules);build 阶段先拷贝到 `agent-env/_incoming/skills/` 并生成 `agent-env/_incoming/manifest.yaml`,S65 再分流写入 `skills/` 与 `rules/` | — |
|
|
178
272
|
| `--baseline-branch <name>` | 可选 | git 基线的分支名(仅 git 模式有效) | `main` |
|
|
179
273
|
| `--baseline-max-file-kb <kb>` | 可选 | 基线拷贝单文件大小上限(KB) | `1024` |
|
|
180
|
-
| `--
|
|
274
|
+
| `--convert-endpoint <url>` | 可选 | build 自动 convert 使用的 markitdown 服务基址;省略时读环境变量 `SVHARNESS_MARKITDOWN_ENDPOINT` | `http://markitdown.desaysz.site` |
|
|
275
|
+
| `--convert-concurrency <n>` | 可选 | build 自动 convert 并发上传数 | `3` |
|
|
276
|
+
| `--convert-max-file-mb <n>` | 可选 | build 自动 convert 单文件大小上限(MB) | `50` |
|
|
277
|
+
| `--convert-timeout-sec <n>` | 可选 | build 自动 convert 请求超时秒数 | `120` |
|
|
278
|
+
| `--convert-force` | 可选 flag | build 自动 convert 覆盖同名 `.md`(否则按 `-1/-2` 追加) | `false` |
|
|
279
|
+
| `--force` | 可选 flag | 覆写已存在的 harness 目录;同时覆写项目根 `AGENTS.md` / `CLAUDE.md`(若存在) | `false` |
|
|
181
280
|
| `-y, --yes` | 可选 flag | 跳过所有提示,采用默认值 | `false` |
|
|
182
281
|
| `--verbose` | 可选 flag | 打印每个生成文件 | `false` |
|
|
183
282
|
|
|
@@ -191,13 +290,13 @@ svharness build \
|
|
|
191
290
|
| `--wiki-model <name>` | LLM 模型名 | `Qwen3.6-27B`(来自内置 wiki 配置链) |
|
|
192
291
|
| `--wiki-base-url <url>` | OpenAI 兼容 API 地址 | `http://model-api.desaysv.com/v1` |
|
|
193
292
|
| `--wiki-api-key <key>` | API Key | 环境变量 `OPENAI_API_KEY` → `.env` → 内置默认 |
|
|
194
|
-
| `--wiki-source <path>` | wiki 扫描的仓库根路径 | `<target>/
|
|
293
|
+
| `--wiki-source <path>` | wiki 扫描的仓库根路径 | `<target>/baseline/code/`(无 baseline 时为 cwd) |
|
|
195
294
|
|
|
196
295
|
**Wiki 配置优先级**:CLI 参数 > 环境变量 > `.env` 文件 > 内置默认值
|
|
197
296
|
|
|
198
297
|
**Wiki 模式总览**:
|
|
199
298
|
|
|
200
|
-
| 组合 | 行为 |
|
|
299
|
+
| 组合 | 行为 | S10_wiki 状态 |
|
|
201
300
|
|------|------|---------|
|
|
202
301
|
| 无 `--baseline` | 不生成 wiki | phase 不存在 |
|
|
203
302
|
| `--baseline`(默认) | 一次 LLM 拿 outline,写 `TASKS.md` | `PENDING` + `requires_agent: true` |
|
|
@@ -229,6 +328,17 @@ svharness apply --harness ../my-app-harness --target ./to-apply-project --clone
|
|
|
229
328
|
|
|
230
329
|
**在 Agent IDE 中触发**:对话框输入 `应用 harness-apply-skills-main 完成 xxx 功能开发`,dispatcher 会自动加载 rules、扫描 skills、路由到合适的子能力。
|
|
231
330
|
|
|
331
|
+
同时,CLI 会在**目标项目根**写入 `CLAUDE.md`(`--agent codechat` 或 `claude-code`)或 `AGENTS.md`(`qoder` / `cursor` / `opencode` / `generic`),指向 **harness-apply-skills-main** 与 `AGENTS_APPLY.md`(与 `build` 写入项目根入口的规则一致)。
|
|
332
|
+
|
|
333
|
+
#### references 内容引用 → apply_skill_registry(S60,由 Agent 写入)
|
|
334
|
+
|
|
335
|
+
S60(`harness-build-skill-references-intake`)中,若某份 references 属于**内容引用**(apply 时要按 `references/md/` 原文指导开发),Agent 应:
|
|
336
|
+
|
|
337
|
+
1. 登记 `references/apply-skills-registry.yaml`(`skill_name`、`reference_md`、`description`,可选 `entry` / `source_id`)
|
|
338
|
+
2. 执行 `svharness apply` 时,CLI 将 enabled 项写入 `harness-apply-skills-main` 绑定元数据的 `apply_skill_registry`;运行期由 apply-main 读 registry + `references/md/` 路由,**不向目标项目注入** `harness-apply-skills-*` 子目录
|
|
339
|
+
|
|
340
|
+
无单独 CLI;规制约束、纯手册类 references **不**登记 registry。
|
|
341
|
+
|
|
232
342
|
#### 双模式对比
|
|
233
343
|
|
|
234
344
|
| 模式 | 标志 | harness 位置 | binding.yaml `mode` | 适用场景 |
|
|
@@ -242,9 +352,9 @@ svharness apply --harness ../my-app-harness --target ./to-apply-project --clone
|
|
|
242
352
|
|------|----------|------|--------|
|
|
243
353
|
| `--harness <path>` | ✅ 必填 | 已构建好的 harness 目录(形如 `./my-app-harness`) | — |
|
|
244
354
|
| `--target <path>` | 可选 | 目标项目根目录 | **当前工作目录(cwd)** |
|
|
245
|
-
| `--agent <agent>` | 可选 | 目标 Agent:`codechat` / `qoder` / `cursor` / `claude-code` / `generic` | **从 `<harness>/.harness-build-state.yaml` 读取**;缺失则报错 |
|
|
355
|
+
| `--agent <agent>` | 可选 | 目标 Agent:`codechat` / `qoder` / `cursor` / `claude-code` / `opencode` / `generic` | **从 `<harness>/.harness-build-state.yaml` 读取**;缺失则报错 |
|
|
246
356
|
| `--clone` | 可选 flag | 完整拷贝 harness 到目标项目根下 | `false`(即 bind-only) |
|
|
247
|
-
| `--force` | 可选 flag | 覆盖已存在的 dispatcher skill 目录(clone
|
|
357
|
+
| `--force` | 可选 flag | 覆盖已存在的 dispatcher skill 目录(clone 模式下同时覆盖克隆目标);并覆盖项目根 `CLAUDE.md`/`AGENTS.md` 与 `AGENTS_APPLY.md` | `false` |
|
|
248
358
|
| `-y, --yes` | 可选 flag | 跳过交互确认 | `false` |
|
|
249
359
|
| `--verbose` | 可选 flag | 显示详细日志 | `false` |
|
|
250
360
|
|
|
@@ -252,6 +362,8 @@ svharness apply --harness ../my-app-harness --target ./to-apply-project --clone
|
|
|
252
362
|
|
|
253
363
|
```
|
|
254
364
|
<target>/
|
|
365
|
+
├── CLAUDE.md | AGENTS.md # apply 工作流入口(按 --agent;已存在时默认跳过)
|
|
366
|
+
├── AGENTS_APPLY.md # harness 应用指南(harness 内模板生成后拷贝)
|
|
255
367
|
├── <adapter.skillsDir>/harness-apply-skills-main/
|
|
256
368
|
│ ├── SKILL.{md|mdc} # dispatcher skill 本体(含 frontmatter 触发词
|
|
257
369
|
│ │ # + 末尾 ## 绑定元数据 内嵌 YAML 块,权威来源)
|
|
@@ -277,6 +389,70 @@ applied_by: svharness@0.8.0
|
|
|
277
389
|
> - 同路径自拷贝会被自动跳过(防御性校验)。
|
|
278
390
|
> - `--agent` 省略时从 harness 构建状态文件读取,确保与原 IDE 一致;若状态文件缺失则报错。
|
|
279
391
|
|
|
392
|
+
### `convert` —— 文档 → Markdown 预处理(对接 S20_collect_inputs)
|
|
393
|
+
|
|
394
|
+
把本地原始需求文档(`.pdf / .docx / .pptx / .xlsx / .html / .epub / .txt / .csv / .json / ...`)通过**云端部署**的 `markitdown_serve`(FastAPI + Microsoft MarkItDown)批量转为 Markdown,产物统一落到 `<harness>/<type>/md/`(`type` 为 `requirements` 或 `references`),直接喂给下游 `S40_extract_requirements` 条目化流程,显著提升 specs 生成质量的稳定性。
|
|
395
|
+
|
|
396
|
+
> **架构约束**:CLI 只是 HTTP 客户端,**不 spawn / 不装 Python / 不管进程**。服务端代码集中在 `svharnessbuild/markitdown_serve/` 便于仓内维护,但**不随 npm 包分发**,部署方式详见 [markitdown_serve/README.md](./markitdown_serve/README.md)。
|
|
397
|
+
|
|
398
|
+
```bash
|
|
399
|
+
# 最简 —— 所有参数均可省略,默认扫描当前目录
|
|
400
|
+
svharness convert
|
|
401
|
+
|
|
402
|
+
# 指定输入和输出目录
|
|
403
|
+
svharness convert --input ./docs/*.pdf ./specs/ --output . --yes
|
|
404
|
+
|
|
405
|
+
# 显示处理日志
|
|
406
|
+
svharness convert --verbose
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
#### 全部参数
|
|
410
|
+
|
|
411
|
+
| 参数 | 说明 | 默认值 |
|
|
412
|
+
|------|------|--------|
|
|
413
|
+
| `--input <path...>` | 一个或多个源文件 / 目录 / glob,支持 `./a/*.pdf`、`./docs/**/*.docx`、`./{a,b}/*.md` | `.`(当前目录) |
|
|
414
|
+
| `--harness <path>` | 目标 harness 目录(需包含 `harness.yaml`);省略时等同 `--output` | `--output` 值 |
|
|
415
|
+
| `--output <path>` | Markdown 输出基目录,产物落到 `<harness>/<type>/md/` | `.`(当前目录) |
|
|
416
|
+
| `--endpoint <url>` | 云端 `markitdown_serve` 基址,省略时读环境变量 `SVHARNESS_MARKITDOWN_ENDPOINT` | `http://markitdown.desaysz.site` |
|
|
417
|
+
| `--concurrency <n>` | 并发上传数 | `3` |
|
|
418
|
+
| `--max-file-mb <n>` | 单文件大小上限(MB),本地 + 服务端双重限流 | `50` |
|
|
419
|
+
| `--timeout-sec <n>` | 单请求超时秒数 | `120`(2 分钟) |
|
|
420
|
+
| `--type <type>` | 目标子目录:`requirements`(正式需求)\| `references`(参考资料) | `requirements` |
|
|
421
|
+
| `--force` | flag,覆盖已存在同名 `.md`(默认自动追加 `-1`、`-2` 后缀) | `false` |
|
|
422
|
+
| `-y, --yes` | flag,跳过交互确认 | `false` |
|
|
423
|
+
| `--verbose` | flag,显示详细日志 | `false` |
|
|
424
|
+
|
|
425
|
+
#### 行为要点
|
|
426
|
+
|
|
427
|
+
- **健康探针前置**:上传前先 `GET /healthz`,不通直接退出并打印清晰定位指引(endpoint / 环境变量 / 服务端目录三条线索)。
|
|
428
|
+
- **单文件失败不中断**:失败单文件计入汇总,其它文件照常完成。结束时打印 `ok / skipped / failed` 计数。
|
|
429
|
+
- **本地白名单预过滤**:客户端与服务端的扩展名白名单保持一致,非白名单文件本地直接跳过,避免无意义往返。
|
|
430
|
+
- **产物目录固定**:Markdown 只写入 `<harness>/<type>/md/`;扫描 `raw/` 时会跳过 `converted_md/`、`md/`、`yaml/` 等目录,并在结束后把误落在 `raw/**/converted_md/` 下的 `.md` 自动迁回 `<type>/md/`。
|
|
431
|
+
- **只写入 `--output` 指定目录**:原文件不移动、不删除,便于用户回溯。
|
|
432
|
+
|
|
433
|
+
#### 产物
|
|
434
|
+
|
|
435
|
+
```
|
|
436
|
+
<harness>/
|
|
437
|
+
└── requirements/ # --type requirements(默认)
|
|
438
|
+
│ └── md/
|
|
439
|
+
│ ├── 需求.md
|
|
440
|
+
│ └── ...
|
|
441
|
+
└── references/ # --type references
|
|
442
|
+
└── md/
|
|
443
|
+
├── 参考文档.md
|
|
444
|
+
└── ...
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
#### 接口契约(CLI ⇄ markitdown_serve)
|
|
448
|
+
|
|
449
|
+
| 端点 | 方法 | 约定 |
|
|
450
|
+
|---|---|---|
|
|
451
|
+
| `/healthz` | GET | 200 `{status, markitdown_version}` |
|
|
452
|
+
| `/convert` | POST | multipart/form-data,字段 `file`;200 返回 `{markdown, source_name, mime}`;413/415/500 带结构化 `error` 字段 |
|
|
453
|
+
|
|
454
|
+
完整契约与部署说明见 [markitdown_serve/README.md](./markitdown_serve/README.md)。
|
|
455
|
+
|
|
280
456
|
---
|
|
281
457
|
|
|
282
458
|
## 架构模板
|
|
@@ -364,6 +540,11 @@ svharness build --harness-name my-app --yes
|
|
|
364
540
|
# 显式指定全部参数
|
|
365
541
|
svharness build --harness-name my-app --arch android-compose --agent qoder --yes
|
|
366
542
|
|
|
543
|
+
# 额外运行期资源(单入口,可混放 skills/rules,先入 _incoming)
|
|
544
|
+
svharness build \
|
|
545
|
+
--harness-name my-app --arch android-compose --agent codechat \
|
|
546
|
+
--extra-skills ./extras ./rules/*.mdc --yes
|
|
547
|
+
|
|
367
548
|
# 本地基线 + wiki 生成
|
|
368
549
|
svharness build \
|
|
369
550
|
--harness-name my-app --arch android-compose --agent codechat \
|
|
@@ -493,6 +674,61 @@ pwsh -File .\scripts\smoke-test.ps1
|
|
|
493
674
|
|
|
494
675
|
构建 TS → 临时目录 `build` → 校验文件 → `--force` 覆写验证。
|
|
495
676
|
|
|
677
|
+
### 演示与 `--extra-skills` 验收
|
|
678
|
+
|
|
679
|
+
端到端演示(requirements + references + baseline + extra-skills 混放)见 **[`demo_project/README.md`](./demo_project/README.md)**。在 `svharnessbuild/` 下:
|
|
680
|
+
|
|
681
|
+
```powershell
|
|
682
|
+
svharness build --harness-name demo-py --arch python --agent codechat `
|
|
683
|
+
--baseline ./demo_project/baseline `
|
|
684
|
+
--requirements ./demo_project/requirements `
|
|
685
|
+
--references ./demo_project/references `
|
|
686
|
+
--extra-skills ./demo_project/extra-skills `
|
|
687
|
+
--yes --force
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
`demo_project/extra-skills/` 布局:
|
|
691
|
+
|
|
692
|
+
| 路径 | intake `detected_type` |
|
|
693
|
+
|------|------------------------|
|
|
694
|
+
| `harness-apply-skills-test-generator/SKILL.md` | `skill` |
|
|
695
|
+
| `harness-apply-skills-python-code-review/SKILL.md` | `skill` |
|
|
696
|
+
| `harness-apply-rules-demo-calculator.mdc` | `rule` |
|
|
697
|
+
| `unknown-sample/readme.txt` | `unknown`(S65 需人工确认) |
|
|
698
|
+
|
|
699
|
+
**分项验收**(仅测 extra-skills 某一类时):
|
|
700
|
+
|
|
701
|
+
```powershell
|
|
702
|
+
# 1) 纯 skills(两个目录,可重复 --extra-skills)
|
|
703
|
+
svharness build --harness-name demo-skills --arch python --agent codechat `
|
|
704
|
+
--extra-skills ./demo_project/extra-skills/harness-apply-skills-test-generator `
|
|
705
|
+
--extra-skills ./demo_project/extra-skills/harness-apply-skills-python-code-review `
|
|
706
|
+
--yes --force
|
|
707
|
+
|
|
708
|
+
# 2) 纯 rule
|
|
709
|
+
svharness build --harness-name demo-rules --arch python --agent codechat `
|
|
710
|
+
--extra-skills ./demo_project/extra-skills/harness-apply-rules-demo-calculator.mdc `
|
|
711
|
+
--yes --force
|
|
712
|
+
|
|
713
|
+
# 3) skills + rules 混放(与端到端相同目录)
|
|
714
|
+
svharness build --harness-name demo-mixed --arch python --agent codechat `
|
|
715
|
+
--extra-skills ./demo_project/extra-skills --yes --force
|
|
716
|
+
|
|
717
|
+
# 4) unknown 资源(需 S65 人工确认类型)
|
|
718
|
+
svharness build --harness-name demo-unknown --arch python --agent codechat `
|
|
719
|
+
--extra-skills ./demo_project/extra-skills/unknown-sample/readme.txt `
|
|
720
|
+
--yes --force
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
验收观察点:
|
|
724
|
+
|
|
725
|
+
- `agent-env/_incoming/skills/` 已导入输入资源;
|
|
726
|
+
- `agent-env/_incoming/manifest.yaml` 包含 `detected_type` 与 `suggested_name`;
|
|
727
|
+
- `.harness-build-state.yaml` 的 `S65_customize_agent_env` 已回填 `incoming_total/skills_count/rules_count/unknown_count`;
|
|
728
|
+
- unknown 或冲突资源仅在 S65 表单确认后落入 `agent-env/skills/` 或 `agent-env/rules/`。
|
|
729
|
+
|
|
730
|
+
> 历史 `fixtures/` 目录已移除,统一由 `demo_project/` 承担演示与 intake 验收。
|
|
731
|
+
|
|
496
732
|
### 注意事项
|
|
497
733
|
|
|
498
734
|
1. **shebang**:`bin/cli.js` 首行必须为 `#!/usr/bin/env node`
|
package/dist/adapters/cursor.js
CHANGED
|
@@ -8,6 +8,7 @@ const _frontmatter_1 = require("./_frontmatter");
|
|
|
8
8
|
*/
|
|
9
9
|
exports.cursorAdapter = {
|
|
10
10
|
name: 'cursor',
|
|
11
|
+
projectEntryFile: 'AGENTS.md',
|
|
11
12
|
skillsDir: '.cursor/rules',
|
|
12
13
|
skillExt: '.mdc',
|
|
13
14
|
transform: (0, _frontmatter_1.ensureMdcFrontmatter)('Harness build helper skill'),
|
package/dist/adapters/generic.js
CHANGED
package/dist/adapters/index.js
CHANGED
|
@@ -7,11 +7,13 @@ const qoder_1 = require("./qoder");
|
|
|
7
7
|
const cursor_1 = require("./cursor");
|
|
8
8
|
const claude_code_1 = require("./claude-code");
|
|
9
9
|
const generic_1 = require("./generic");
|
|
10
|
+
const opencode_1 = require("./opencode");
|
|
10
11
|
const REGISTRY = {
|
|
11
12
|
codechat: codechat_1.codechatAdapter,
|
|
12
13
|
qoder: qoder_1.qoderAdapter,
|
|
13
14
|
cursor: cursor_1.cursorAdapter,
|
|
14
15
|
'claude-code': claude_code_1.claudeCodeAdapter,
|
|
16
|
+
opencode: opencode_1.opencodeAdapter,
|
|
15
17
|
generic: generic_1.genericAdapter,
|
|
16
18
|
};
|
|
17
19
|
function getAdapter(name) {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.opencodeAdapter = void 0;
|
|
4
|
+
const _frontmatter_1 = require("./_frontmatter");
|
|
5
|
+
/**
|
|
6
|
+
* OpenCode (opencode.ai): project skills under `.opencode/skills/<name>/SKILL.md`.
|
|
7
|
+
* @see https://opencode.ai/docs/skills
|
|
8
|
+
*/
|
|
9
|
+
exports.opencodeAdapter = {
|
|
10
|
+
name: 'opencode',
|
|
11
|
+
projectEntryFile: 'AGENTS.md',
|
|
12
|
+
skillsDir: '.opencode/skills',
|
|
13
|
+
skillExt: '.md',
|
|
14
|
+
rulesDir: '.opencode/rules',
|
|
15
|
+
ruleExt: '.mdc',
|
|
16
|
+
ruleTransform: (0, _frontmatter_1.ensureMdcFrontmatter)('Harness build-time rule'),
|
|
17
|
+
};
|
package/dist/adapters/qoder.js
CHANGED
package/dist/commands/apply.js
CHANGED
|
@@ -9,6 +9,8 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
9
9
|
const js_yaml_1 = __importDefault(require("js-yaml"));
|
|
10
10
|
const prompts_1 = __importDefault(require("prompts"));
|
|
11
11
|
const adapters_1 = require("../adapters");
|
|
12
|
+
const apply_project_entry_1 = require("../core/apply-project-entry");
|
|
13
|
+
const reference_apply_skills_1 = require("../core/reference-apply-skills");
|
|
12
14
|
const validate_args_1 = require("../utils/validate-args");
|
|
13
15
|
const logger_1 = require("../utils/logger");
|
|
14
16
|
const version_1 = require("../utils/version");
|
|
@@ -131,8 +133,9 @@ async function runApply(opts) {
|
|
|
131
133
|
}
|
|
132
134
|
}
|
|
133
135
|
if (!agent) {
|
|
134
|
-
throw new Error('无法推断目标 agent。请显式传入 --agent <
|
|
135
|
-
|
|
136
|
+
throw new Error('无法推断目标 agent。请显式传入 --agent <' +
|
|
137
|
+
(0, validate_args_1.listSupportedAgents)().join('|') +
|
|
138
|
+
'>,或确认 harness 下存在 .harness-build-state.yaml。');
|
|
136
139
|
}
|
|
137
140
|
const adapter = (0, adapters_1.getAdapter)(agent);
|
|
138
141
|
// 4. Compute injection target.
|
|
@@ -165,7 +168,7 @@ async function runApply(opts) {
|
|
|
165
168
|
if (cloneMode && effectiveHarnessRoot !== harnessRoot) {
|
|
166
169
|
configRows.push({ label: '克隆目标', value: effectiveHarnessRoot });
|
|
167
170
|
}
|
|
168
|
-
configRows.push({ label: '注入 skill', value: node_path_1.default.relative(targetRoot, skillFile) }, { label: '绑定元数据(冗余副本)', value: node_path_1.default.relative(targetRoot, bindingFile) }, { label: '工具版本', value: `svharness@${cliVersion}` });
|
|
171
|
+
configRows.push({ label: '注入 skill', value: node_path_1.default.relative(targetRoot, skillFile) }, { label: '绑定元数据(冗余副本)', value: node_path_1.default.relative(targetRoot, bindingFile) }, { label: '项目根 AI 入口', value: adapter.projectEntryFile }, { label: '工具版本', value: `svharness@${cliVersion}` });
|
|
169
172
|
logger_1.logger.configBox('apply 配置确认', configRows);
|
|
170
173
|
if (!opts.yes) {
|
|
171
174
|
const { ok } = await (0, prompts_1.default)({
|
|
@@ -209,6 +212,10 @@ async function runApply(opts) {
|
|
|
209
212
|
}
|
|
210
213
|
// 8. Build binding metadata first (needed for both inline rendering into
|
|
211
214
|
// the skill body and the redundant sidecar file).
|
|
215
|
+
const skillRegistry = await (0, reference_apply_skills_1.loadApplySkillRegistry)(effectiveHarnessRoot);
|
|
216
|
+
const applySkillRegistry = skillRegistry
|
|
217
|
+
? (0, reference_apply_skills_1.registryEntriesForBinding)(skillRegistry)
|
|
218
|
+
: [];
|
|
212
219
|
const binding = {
|
|
213
220
|
harness_name: harnessName,
|
|
214
221
|
harness_root: effectiveHarnessRoot,
|
|
@@ -219,6 +226,7 @@ async function runApply(opts) {
|
|
|
219
226
|
mode: cloneMode ? 'clone' : 'bind-only',
|
|
220
227
|
applied_at: appliedAt,
|
|
221
228
|
applied_by: `svharness@${cliVersion}`,
|
|
229
|
+
apply_skill_registry: applySkillRegistry,
|
|
222
230
|
};
|
|
223
231
|
const bindingYaml = '# Generated by `svharness apply`. DO NOT edit by hand.\n' +
|
|
224
232
|
'# Re-run `svharness apply --force` to refresh.\n' +
|
|
@@ -253,12 +261,49 @@ async function runApply(opts) {
|
|
|
253
261
|
logger_1.logger.section(`步骤 ${stepNo}/${totalSteps} - 写入 harness 绑定元数据(冗余副本)`);
|
|
254
262
|
await fs_extra_1.default.outputFile(bindingFile, bindingYaml, 'utf8');
|
|
255
263
|
logger_1.logger.success(`已写入 ${node_path_1.default.relative(targetRoot, bindingFile)}(冗余副本)`);
|
|
264
|
+
if (applySkillRegistry.length > 0) {
|
|
265
|
+
logger_1.logger.success(`已内联 apply_skill_registry ${applySkillRegistry.length} 条(references 内容由 apply-main 路由)`);
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
logger_1.logger.info('未找到 references/apply-skills-registry.yaml,apply_skill_registry 为空');
|
|
269
|
+
logger_1.logger.info(' 请在 S60 为「内容引用」登记 registry 后重新 apply');
|
|
270
|
+
}
|
|
271
|
+
// 9b. Inject AGENTS_APPLY.md into target project root (if present in harness).
|
|
272
|
+
const agentsApplySrc = node_path_1.default.join(harnessRoot, 'AGENTS_APPLY.md');
|
|
273
|
+
if (await fs_extra_1.default.pathExists(agentsApplySrc)) {
|
|
274
|
+
const agentsApplyDest = node_path_1.default.join(targetRoot, 'AGENTS_APPLY.md');
|
|
275
|
+
let shouldCopy = true;
|
|
276
|
+
if (await fs_extra_1.default.pathExists(agentsApplyDest)) {
|
|
277
|
+
if (!opts.force) {
|
|
278
|
+
logger_1.logger.warn(`目标项目已存在 AGENTS_APPLY.md,跳过(使用 --force 覆盖)`);
|
|
279
|
+
shouldCopy = false;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
if (shouldCopy) {
|
|
283
|
+
await fs_extra_1.default.copy(agentsApplySrc, agentsApplyDest, { overwrite: true });
|
|
284
|
+
logger_1.logger.success(`已写入 ${node_path_1.default.relative(targetRoot, agentsApplyDest)}`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
logger_1.logger.debug('harness 中未找到 AGENTS_APPLY.md,跳过注入');
|
|
289
|
+
}
|
|
290
|
+
await (0, apply_project_entry_1.writeApplyProjectEntry)({
|
|
291
|
+
projectRoot: targetRoot,
|
|
292
|
+
adapter,
|
|
293
|
+
harnessRootRel,
|
|
294
|
+
harnessName,
|
|
295
|
+
harnessVersion,
|
|
296
|
+
agent,
|
|
297
|
+
mode: cloneMode ? 'clone' : 'bind-only',
|
|
298
|
+
force: !!opts.force,
|
|
299
|
+
});
|
|
256
300
|
// 10. Next steps hint.
|
|
257
301
|
logger_1.logger.plain('');
|
|
258
302
|
logger_1.logger.plain('✨ harness 已绑定到当前项目');
|
|
259
303
|
logger_1.logger.plain('');
|
|
260
304
|
logger_1.logger.plain(' 下一步:在 agent 中输入');
|
|
261
305
|
logger_1.logger.plain(` 应用 ${DISPATCHER_SKILL_NAME} 完成 <你的功能> 功能开发`);
|
|
306
|
+
logger_1.logger.plain(` 或阅读 ${adapter.projectEntryFile} 与 AGENTS_APPLY.md 了解完整的 harness 应用工作流`);
|
|
262
307
|
logger_1.logger.plain('');
|
|
263
308
|
if (cloneMode && effectiveHarnessRoot !== harnessRoot) {
|
|
264
309
|
logger_1.logger.plain(` harness 内容已克隆至:${node_path_1.default.relative(targetRoot, effectiveHarnessRoot)}/(已纳入目标项目)`);
|