@ck123pm/harness-kit 0.1.1 → 0.1.3

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/PLAN.md CHANGED
@@ -1,123 +1,29 @@
1
- # @ck123pm/harness-kit 设计文档
1
+ # Harness Kit Plan
2
2
 
3
- ## 产品定位
3
+ ## Current Direction
4
4
 
5
- 两段式初始化模型:
5
+ This package now ships the harness capabilities as Claude skills instead of Claude commands.
6
6
 
7
- ```
8
- 第一步:CLI 安装能力
9
- npx @ck123pm/harness-kit install
7
+ Installed artifacts:
10
8
 
11
- 第二步:Claude 执行智能初始化
12
- /harness-init
9
+ - `skills/harness-init/SKILL.md`
10
+ - `skills/harness-update-spec/SKILL.md`
11
+ - `skills/md-to-html-doc.md`
13
12
 
14
- 第三步:CLI Claude 执行 comet 初始化
15
- comet init
16
- ```
13
+ ## Intended Workflow
17
14
 
18
- **产品边界:**
19
- - **harness-kit CLI**:安装 Claude command/skill、检查/安装 comet、环境诊断
20
- - **harness-init.md**:Claude command,由 Claude 理解项目后智能生成 `.harness/`
21
- - **md-to-html-doc.md**:Claude skill,Markdown 转响应式 HTML
22
- - **comet**:后续 OpenSpec + Superpowers workflow 管理
15
+ 1. Run `harness-kit install`.
16
+ 2. Open Claude and ask it to use `harness-init` to create `.harness/`.
17
+ 3. Later, ask Claude to use `harness-update-spec` to refresh stale specs incrementally.
23
18
 
24
- CLI **不直接生成 `.harness/`** —— 真正的 `.harness/` 内容需要大模型理解项目后生成。
19
+ ## CLI Responsibilities
25
20
 
26
- ## 目录结构
21
+ - Install packaged skills into Claude config.
22
+ - Check optional external tools such as `comet` and `openspec`.
23
+ - Diagnose environment state.
24
+ - Update or uninstall installed skill artifacts.
27
25
 
28
- ```
29
- @ck123pm/harness-kit
30
- ├── bin/
31
- │ └── harness-kit.js # CLI shebang 入口
32
- ├── src/
33
- │ ├── cli.js # Commander 程序定义
34
- │ ├── commands/
35
- │ │ ├── install.js # install 命令
36
- │ │ ├── doctor.js # doctor 命令
37
- │ │ ├── update.js # update 命令
38
- │ │ └── uninstall.js # uninstall 命令
39
- │ └── utils/
40
- │ ├── platform.js # 平台检测(Windows/Mac/Linux 路径差异)
41
- │ └── registry.js # command/skill 安装路径解析
42
- ├── commands/
43
- │ └── harness-init.md # Claude command(智能初始化指令)
44
- ├── skills/
45
- │ └── md-to-html-doc.md # Claude skill
46
- ├── scripts/
47
- │ └── init-comet.js # 独立脚本:执行 comet init
48
- ├── package.json
49
- └── README.md
50
- ```
26
+ ## Notes
51
27
 
52
- ## CLI 命令定义
53
-
54
- ### `harness-kit install`
55
-
56
- 安装 harness 能力到 Claude 环境:
57
-
58
- 1. **检测 Claude 配置路径**:解析 `~/.claude/` 或 `CLAUDE_CONFIG_DIR` 环境变量
59
- 2. **安装 harness-init.md 到 commands**:复制 `commands/harness-init.md` → `~/.claude/commands/harness-init.md`
60
- 3. **安装 md-to-html-doc.md 到 skills**:复制 `skills/md-to-html-doc.md` → `~/.claude/skills/md-to-html-doc.md`
61
- 4. **检查/安装 @ck123pm/comet**:检测 `comet` 是否在 PATH,不在则 `npm install -g @ck123pm/comet`
62
- 5. **检查/安装 openspec**:检测 `openspec` 是否在 PATH,不在则 `npm install -g @fission-ai/openspec`
63
- 6. **写入安装记录**:`~/.claude/harness-kit.json`
64
- 7. **提示用户下一步**:"Open Claude and run `/harness-init` to initialize your project"
65
-
66
- 选项:
67
- - `--scope <scope>`: global (默认) | local(安装到项目 .claude/ 而非全局)
68
- - `--skip-comet`: 跳过 comet 安装
69
- - `--skip-openspec`: 跳过 openspec 安装
70
- - `--force`: 覆盖已有文件
71
-
72
- ### `harness-kit doctor`
73
-
74
- 环境健康检查,打印表格,每项绿色 ✓ 或红色 ✗:
75
-
76
- - [ ] Claude command harness-init 是否已安装
77
- - [ ] Claude skill md-to-html-doc 是否已安装
78
- - [ ] comet 是否可用(版本)
79
- - [ ] openspec 是否可用(版本)
80
- - [ ] superpowers 是否可用
81
- - [ ] 当前目录是否已有 `.harness/`
82
- - [ ] 当前目录是否已有 `.comet.yaml`
83
- - [ ] 当前目录是否已有 `openspec/`
84
-
85
- 末尾给出修复建议。
86
-
87
- ### `harness-kit update`
88
-
89
- 升级已安装的 command/skill:
90
-
91
- 1. 对比已安装文件与包内文件的哈希/大小
92
- 2. 如果有更新:提示用户,确认后覆盖
93
- 3. 如果已是最新:打印 "Up to date"
94
- 4. 可选:`--check` 仅检查不升级
95
-
96
- ### `harness-kit uninstall`
97
-
98
- 卸载已安装的 command/skill:
99
-
100
- 1. 删除 `~/.claude/commands/harness-init.md`
101
- 2. 删除 `~/.claude/skills/md-to-html-doc.md`
102
- 3. 删除 `~/.claude/harness-kit.json`
103
- 4. 打印确认信息
104
-
105
- ## 依赖配置
106
-
107
- - **dependencies**: commander (^14.0.0), chalk (^5.3.0), fs-extra (^11.2.0)
108
- - **peerDependencies**: @ck123pm/comet (>=0.2.0), @fission-ai/openspec (>=1.0.0)
109
- - **peerDependenciesMeta**: 两者 optional: true
110
- - **engines**: node >= 20
111
- - **publishConfig**: { "access": "public" }
112
- - **type**: "module"
113
-
114
- ## 验证方式
115
-
116
- 1. `npm install` 安装依赖
117
- 2. `node bin/harness-kit.js install` — 安装到全局
118
- 3. `node bin/harness-kit.js doctor` — 验证环境
119
- 4. 打开 Claude,执行 `/harness-init` — 验证 Claude 能识别 command
120
- 5. `node bin/harness-kit.js update` — 验证升级检测
121
- 6. `node bin/harness-kit.js uninstall` — 验证卸载
122
- 7. 测试 `--scope local` 安装到项目 `.claude/`
123
- 8. 测试 `--force` 覆盖
28
+ - `harness-init` and `harness-update-spec` are directory-based skills.
29
+ - The install/update record logic must support hashing whole directories, not only single files.
package/README.md CHANGED
@@ -1,185 +1,115 @@
1
1
  # @ck123pm/harness-kit
2
2
 
3
- CLI for installing and managing Claude Code harness capabilities.
3
+ CLI for installing and managing harness-related Claude skills.
4
4
 
5
- ## 安装
5
+ ## Install
6
6
 
7
7
  ```bash
8
8
  npx @ck123pm/harness-kit install
9
9
  ```
10
10
 
11
- 或全局安装后使用:
11
+ Or install globally first:
12
12
 
13
13
  ```bash
14
14
  npm install -g @ck123pm/harness-kit
15
15
  harness-kit install
16
16
  ```
17
17
 
18
- ## 使用流程
18
+ ## What Gets Installed
19
19
 
20
- 三步初始化模型:
20
+ `harness-kit install` installs these Claude skills:
21
21
 
22
- ```
23
- 第一步:CLI 安装能力
24
- npx @ck123pm/harness-kit install
22
+ - `harness-init`
23
+ - `harness-update-spec`
24
+ - `md-to-html-doc`
25
25
 
26
- 第二步:Claude 执行智能初始化
27
- /harness-init
26
+ It also checks for:
28
27
 
29
- 第三步:CLI 或 Claude 执行 comet 初始化
30
- comet init
31
- ```
28
+ - `@ck123pm/comet`
29
+ - `@fission-ai/openspec`
32
30
 
33
- ## CLI 命令
31
+ And writes an install record to `~/.claude/harness-kit.json` or the local `.claude/` scope.
34
32
 
35
- ### `harness-kit install`
33
+ ## Usage Flow
36
34
 
37
- 安装 harness 能力到 Claude 环境:
35
+ 1. Install the skills with `harness-kit install`.
36
+ 2. Open Claude and ask it to use the `harness-init` skill to initialize the project harness.
37
+ 3. After the harness exists, ask Claude to use the `harness-update-spec` skill when specs need to be refreshed.
38
+ 4. Use `comet init` or `openspec` commands as needed for the surrounding workflow.
39
+
40
+ ## CLI Commands
41
+
42
+ ### `harness-kit install`
38
43
 
39
- - 复制 `harness-init.md` `~/.claude/commands/`
40
- - 复制 `harness-update-spec.md` → `~/.claude/commands/`
41
- - 复制 `md-to-html-doc.md` → `~/.claude/skills/`
42
- - 检查/安装 `@ck123pm/comet`
43
- - 检查/安装 `@fission-ai/openspec`
44
- - 写入安装记录 `~/.claude/harness-kit.json`
44
+ Install the packaged Claude skills.
45
45
 
46
- **选项:**
46
+ Options:
47
47
 
48
- | 选项 | 说明 |
49
- |------|------|
50
- | `--scope <scope>` | `global`(默认)或 `local`(安装到项目 `.claude/`) |
51
- | `--skip-comet` | 跳过 comet 安装 |
52
- | `--skip-openspec` | 跳过 openspec 安装 |
53
- | `--force` | 覆盖已有文件 |
48
+ - `--scope <scope>`: `global` or `local`
49
+ - `--skip-comet`: skip `@ck123pm/comet` install check
50
+ - `--skip-openspec`: skip `@fission-ai/openspec` install check
51
+ - `--force`: overwrite installed files
54
52
 
55
- **示例:**
53
+ Examples:
56
54
 
57
55
  ```bash
58
- # 全局安装(默认)
59
56
  harness-kit install
60
-
61
- # 安装到项目级 .claude/
62
57
  harness-kit install --scope local
63
-
64
- # 跳过 comet 和 openspec
65
58
  harness-kit install --skip-comet --skip-openspec
66
59
  ```
67
60
 
68
61
  ### `harness-kit doctor`
69
62
 
70
- 环境健康检查,打印各项状态:
71
-
72
- ```
73
- 🔍 harness-kit doctor
74
-
75
- ✓ Claude command harness-init Found
76
- ✓ Claude command harness-update-spec Found
77
- ✓ Claude skill md-to-html-doc Found
78
- ✗ comet Not found
79
- ✗ openspec Not found
80
- ✓ superpowers Built-in
81
- ✗ .harness/ Not found
82
- ✗ .comet.yaml Not found
83
- ✗ openspec/ Not found
84
- ```
85
-
86
- 末尾给出修复建议。
63
+ Check whether the required skills and supporting tools are present.
87
64
 
88
65
  ### `harness-kit update`
89
66
 
90
- 升级已安装的 command/skill
67
+ Update installed skill files from the current package contents.
91
68
 
92
- - 对比已安装文件与包内文件的哈希
93
- - 有更新时提示确认后覆盖
94
- - 已是最新时打印 "All files up to date"
69
+ Options:
95
70
 
96
- **选项:**
97
-
98
- | 选项 | 说明 |
99
- |------|------|
100
- | `--check` | 仅检查不升级 |
101
- | `--force` | 强制覆盖不提示 |
102
-
103
- **示例:**
104
-
105
- ```bash
106
- # 检查是否有更新
107
- harness-kit update --check
108
-
109
- # 执行更新
110
- harness-kit update
111
- ```
71
+ - `--check`: detect updates without applying them
72
+ - `--force`: overwrite without prompting
112
73
 
113
74
  ### `harness-kit uninstall`
114
75
 
115
- 卸载已安装的 command/skill
76
+ Remove installed skill files and the install record.
116
77
 
117
- ```bash
118
- harness-kit uninstall
119
- ```
78
+ ## Installed Skills
120
79
 
121
- 删除 `~/.claude/commands/harness-init.md`、`harness-update-spec.md`、`skills/md-to-html-doc.md` 和 `harness-kit.json`。
80
+ ### `harness-init`
122
81
 
123
- ## Claude Commands
82
+ Initializes the `.harness/` directory from the real codebase and splits project knowledge into the expected harness structure.
124
83
 
125
- 安装后在 Claude 中可用的斜杠命令:
84
+ ### `harness-update-spec`
126
85
 
127
- | 命令 | 说明 |
128
- |------|------|
129
- | `/harness-init` | 智能初始化 `.harness/` 目录,基于项目代码推导生成全部 spec |
130
- | `/harness-update-spec` | 分析当前项目状态,对比现有 `.harness/` spec,交互式建议更新或新增 |
86
+ Compares the current codebase against the existing `.harness/` specs and proposes or applies incremental updates.
131
87
 
132
- ## .harness/ 目录结构
88
+ ### `md-to-html-doc`
133
89
 
134
- `/harness-init` 生成的目录:
90
+ Converts Markdown architecture and guide documents into responsive HTML output.
135
91
 
136
- ```
92
+ ## Expected `.harness/` Structure
93
+
94
+ ```text
137
95
  .harness/
138
- ├── README.md # 使用说明
96
+ ├── README.md
139
97
  ├── index/
140
- │ ├── routing.md # 任务→上下文路由
141
- │ ├── priority.md # 注入优先级 (MUST/SHOULD/HINT)
142
- │ ├── module-map.md # 模块→spec 映射
143
- │ └── project-profile.md # 项目身份卡片
144
98
  ├── rules/
145
- │ ├── architecture.md # 架构约束
146
- │ ├── coding.md # 编码规范
147
- │ ├── testing.md # 测试规则
148
- │ └── security.md # 安全约束
149
99
  ├── domain/
150
- │ ├── glossary.md # 领域术语
151
- │ ├── business-rules.md # 业务规则
152
- │ └── runtime-semantics.md # 运行时语义
153
100
  ├── decisions/
154
- │ ├── adr/ # 架构决策记录
155
- │ └── tradeoffs.md # 设计权衡
156
101
  ├── guides/
157
- │ ├── backend.md # 后端执行手册
158
- │ └── ops.md # 运维操作指南
159
102
  ├── memory/
160
- │ ├── pitfalls.md # 踩坑经验
161
- │ ├── regressions.md # 回归问题
162
- │ ├── patterns.md # 可复用模式
163
- │ └── lessons.md # 经验总结
164
103
  └── human-docs/
165
- ├── onboarding.html # 新人手册
166
- ├── architecture-intro.html # 架构介绍
167
- └── operation-manual.html # 操作手册
168
104
  ```
169
105
 
170
- ## Claude Skill
171
-
172
- | Skill | 说明 |
173
- |-------|------|
174
- | `md-to-html-doc` | Markdown 转响应式 HTML(含侧边栏导航、flexbox 流程图) |
175
-
176
- ## 环境要求
106
+ ## Requirements
177
107
 
178
108
  - Node.js >= 20
179
109
  - Claude Code CLI
180
- - `@ck123pm/comet`(可选)
181
- - `@fission-ai/openspec`(可选)
110
+ - `@ck123pm/comet` optional
111
+ - `@fission-ai/openspec` optional
182
112
 
183
113
  ## License
184
114
 
185
- MIT
115
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ck123pm/harness-kit",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "CLI for installing and managing Claude Code harness capabilities",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: harness-init
3
+ description: Initialize a project's .harness/ directory by deriving high-value project knowledge from the real codebase, splitting content into the expected index/rules/domain/decisions/guides/memory/human-docs structure, and avoiding facts that can be re-derived from source.
4
+ ---
5
+
6
+ # Harness Init
7
+
8
+ Use this skill when the user wants to initialize a project's `.harness/` directory from the current codebase state.
9
+
10
+ ## Core Principles
11
+
12
+ 1. Do not record what the AI can cheaply derive from source code.
13
+ 2. Split expensive-to-derive knowledge by type and place it in the right file.
14
+ 3. Put design decisions, historical reasons, and tradeoffs into `decisions/`.
15
+ 4. Put human-oriented docs in `human-docs/` as Markdown first, convert them to HTML with `md-to-html-doc`, then remove the Markdown source if the workflow requires generated HTML only.
16
+ 5. Never fabricate content that is not supported by the actual repository state.
17
+
18
+ ## Target Directory Structure
19
+
20
+ Create this structure under `.harness/`:
21
+
22
+ ```text
23
+ .harness/
24
+ ├── README.md
25
+ ├── index/
26
+ │ ├── routing.md
27
+ │ ├── priority.md
28
+ │ ├── module-map.md
29
+ │ └── project-profile.md
30
+ ├── rules/
31
+ │ ├── architecture.md
32
+ │ ├── coding.md
33
+ │ ├── testing.md
34
+ │ └── security.md
35
+ ├── domain/
36
+ │ ├── glossary.md
37
+ │ ├── business-rules.md
38
+ │ └── runtime-semantics.md
39
+ ├── decisions/
40
+ │ ├── adr/
41
+ │ └── tradeoffs.md
42
+ ├── guides/
43
+ │ ├── backend.md
44
+ │ └── ops.md
45
+ ├── memory/
46
+ │ ├── pitfalls.md
47
+ │ ├── regressions.md
48
+ │ ├── patterns.md
49
+ │ └── lessons.md
50
+ └── human-docs/
51
+ ├── onboarding.html
52
+ ├── architecture-intro.html
53
+ └── operation-manual.html
54
+ ```
55
+
56
+ ## Content Routing
57
+
58
+ | Information type | Destination |
59
+ | --- | --- |
60
+ | Project identity, tech stack, module structure, key constants | `index/project-profile.md` |
61
+ | Task-to-context routing | `index/routing.md` |
62
+ | Injection priority and intensity | `index/priority.md` |
63
+ | Module-to-spec mapping | `index/module-map.md` |
64
+ | Architecture constraints, module boundaries, ownership, high-risk chains | `rules/architecture.md` |
65
+ | Coding standards, serialization, locking, conventions | `rules/coding.md` |
66
+ | Test framework, file layout, strategy, fast commands | `rules/testing.md` |
67
+ | Security constraints | `rules/security.md` |
68
+ | Domain terminology | `domain/glossary.md` |
69
+ | Stable business rules | `domain/business-rules.md` |
70
+ | Runtime semantics, state transitions, magic values | `domain/runtime-semantics.md` |
71
+ | External-system runtime semantics, message flow, integration behavior | `guides/backend.md` |
72
+ | Build, startup, logs, config, monitoring, troubleshooting | `guides/ops.md` |
73
+ | ADRs and tradeoffs | `decisions/` |
74
+ | Historical pitfalls, regressions, reusable patterns, lessons | `memory/` |
75
+
76
+ ## Exploration Strategy
77
+
78
+ Before writing files, inspect the repository in at least three passes:
79
+
80
+ 1. Project metadata and top-level docs: `package.json`, `pom.xml`, `README`, `AGENTS.md`, workspace config.
81
+ 2. Module boundaries and entry points: application bootstraps, services, APIs, entities, consumers, producers, config, tests.
82
+ 3. Runtime and history signals: external integrations, state machines, queues, locks, transactions, recent commits, regressions.
83
+
84
+ Prefer CodeGraph when it is available. Use local search only when you need literal text or filesystem details.
85
+
86
+ ## Language
87
+
88
+ Before generating any content, determine the output language:
89
+
90
+ 1. Read the project's `CLAUDE.md` (or `.claude/CLAUDE.md`) if it exists. If it declares a language preference (e.g. `language: zh-CN`, "使用中文", "write in English"), follow that.
91
+ 2. If no language preference is found, match the language of the current conversation.
92
+ 3. All generated files in `.harness/` must use the same language consistently.
93
+
94
+ ## Execution
95
+
96
+ 1. Explore the repository thoroughly and base all outputs on the current branch state.
97
+ 2. Create the full `.harness/` tree, even if some files are initially brief.
98
+ 3. Keep generated content concise and high-signal.
99
+ 4. If `human-docs/` content is needed, write Markdown first, then use `md-to-html-doc` to produce HTML.
100
+ 5. Verify the final `.harness/` tree is complete.
@@ -0,0 +1,96 @@
1
+ ---
2
+ name: harness-update-spec
3
+ description: Analyze an existing project's .harness/ specs against the current codebase, identify incremental updates or missing specs, and propose focused changes without regenerating everything from scratch.
4
+ ---
5
+
6
+ # Harness Update Spec
7
+
8
+ Use this skill when the user wants to inspect whether an existing `.harness/` directory is stale and update it incrementally.
9
+
10
+ ## Core Principles
11
+
12
+ 1. Use the current `.harness/` content as the baseline and compare it with the real codebase state.
13
+ 2. Focus on incremental changes: what changed, what is missing, and what should be amended.
14
+ 3. Prefer interactive confirmation when the user wants review-first behavior; otherwise execute the requested updates directly.
15
+ 4. Do not add facts that can be cheaply re-derived from source code.
16
+ 5. Preserve historical records in `decisions/` and `memory/` by appending when appropriate instead of overwriting blindly.
17
+
18
+ ## Analysis Flow
19
+
20
+ ### 1. Scan existing `.harness/`
21
+
22
+ Read the current `.harness/` files and build a quick index of:
23
+
24
+ - Which spec files already exist.
25
+ - What each file currently covers.
26
+ - Which expected files are missing.
27
+
28
+ If `.harness/` does not exist, stop and tell the user to initialize it with the `harness-init` skill first.
29
+
30
+ ### 2. Re-scan the project
31
+
32
+ Inspect the live repository in at least three passes:
33
+
34
+ 1. Tech stack changes: dependency additions, removals, or upgrades.
35
+ 2. Module boundary changes: new or removed modules, services, entry points, entities.
36
+ 3. Runtime flow changes: new consumers, producers, RPC edges, topics, configs, transactions, locks, external integrations.
37
+ 4. High-risk chain changes: new distributed behavior, critical state transitions, external dependencies.
38
+ 5. Recent git history: commits that imply architectural or behavior changes.
39
+
40
+ Prefer CodeGraph when it is available.
41
+
42
+ ### 3. Derive a diff matrix
43
+
44
+ Map detected changes to spec targets:
45
+
46
+ | Change type | Likely spec target |
47
+ | --- | --- |
48
+ | Dependency or runtime identity changes | `index/project-profile.md` |
49
+ | Module structure changes | `index/module-map.md` |
50
+ | New services, consumers, producers, RPC or message flows | `guides/backend.md` |
51
+ | New runtime semantics or state machines | `domain/runtime-semantics.md` |
52
+ | Architecture boundary changes | `rules/architecture.md` |
53
+ | New design tradeoffs or ADR-worthy decisions | `decisions/tradeoffs.md` or `decisions/adr/` |
54
+ | New domain terms or business rules | `domain/glossary.md`, `domain/business-rules.md` |
55
+ | New pitfalls, regressions, or reusable patterns | `memory/` |
56
+
57
+ ### 4. Report proposed updates
58
+
59
+ When the user asks for analysis first, present a compact report that includes:
60
+
61
+ - Newly detected changes.
62
+ - Missing spec files.
63
+ - Which `.harness/` files should be updated and why.
64
+
65
+ If the user asks you to proceed, apply only the selected or clearly necessary updates.
66
+
67
+ ### 5. Apply updates
68
+
69
+ When updating:
70
+
71
+ 1. Do not rewrite correct existing content without reason.
72
+ 2. Append to history-oriented files when that better preserves context.
73
+ 3. Keep internal references inside `.harness/` consistent after edits.
74
+ 4. Re-run a quick file list check to ensure the directory remains coherent.
75
+
76
+ ## Content Routing
77
+
78
+ Reuse the same content-routing rules as `harness-init`:
79
+
80
+ - Project identity goes to `index/project-profile.md`.
81
+ - Data flow and external runtime semantics go to `guides/backend.md`.
82
+ - High-risk chains and boundaries go to `rules/architecture.md`.
83
+ - Decisions and tradeoffs go to `decisions/`.
84
+ - Historical pitfalls, regressions, and patterns go to `memory/`.
85
+
86
+ ## Language
87
+
88
+ Before generating or updating any content, determine the output language using the same rules as `harness-init`:
89
+
90
+ 1. Read the project's `CLAUDE.md` (or `.claude/CLAUDE.md`) if it exists. If it declares a language preference, follow that.
91
+ 2. If no preference is found, match the language of the current conversation.
92
+ 3. All generated files in `.harness/` must use the same language consistently and match the language of existing `.harness/` files.
93
+
94
+ ## Human Docs
95
+
96
+ If you add or refresh `human-docs/` content, write Markdown first and then use `md-to-html-doc` to produce the HTML artifacts expected by the harness.
package/src/cli.js CHANGED
@@ -15,7 +15,7 @@ program
15
15
 
16
16
  program
17
17
  .command('install')
18
- .description('Install harness-init command and md-to-html-doc skill to Claude')
18
+ .description('Install harness skills into Claude')
19
19
  .option('--scope <scope>', 'Installation scope: global or local', 'global')
20
20
  .option('--skip-comet', 'Skip @ck123pm/comet installation')
21
21
  .option('--skip-openspec', 'Skip @fission-ai/openspec installation')
@@ -39,7 +39,7 @@ program
39
39
 
40
40
  program
41
41
  .command('update')
42
- .description('Update installed command/skill files')
42
+ .description('Update installed skill files')
43
43
  .option('--check', 'Check for updates without installing')
44
44
  .option('--force', 'Force overwrite without prompting')
45
45
  .action(async (options) => {
@@ -49,7 +49,7 @@ program
49
49
 
50
50
  program
51
51
  .command('uninstall')
52
- .description('Remove installed command/skill files')
52
+ .description('Remove installed skill files')
53
53
  .action(async () => {
54
54
  const { default: action } = await import('./commands/uninstall.js');
55
55
  await action();
@@ -12,19 +12,19 @@ export default async function doctorAction() {
12
12
 
13
13
  const checks = [];
14
14
 
15
- // Check 1: Claude command harness-init (check both scopes)
16
- let cmdPath = null;
17
- const globalCmd = resolveTargetPath('commands/harness-init.md', 'global');
18
- const localCmd = resolveTargetPath('commands/harness-init.md', 'local');
19
- if (await fs.pathExists(globalCmd)) {
20
- cmdPath = globalCmd;
21
- } else if (await fs.pathExists(localCmd)) {
22
- cmdPath = localCmd;
15
+ // Check 1: Claude skill harness-init (check both scopes)
16
+ let initSkillPath = null;
17
+ const globalInitSkill = resolveTargetPath('skills/harness-init/SKILL.md', 'global');
18
+ const localInitSkill = resolveTargetPath('skills/harness-init/SKILL.md', 'local');
19
+ if (await fs.pathExists(globalInitSkill)) {
20
+ initSkillPath = globalInitSkill;
21
+ } else if (await fs.pathExists(localInitSkill)) {
22
+ initSkillPath = localInitSkill;
23
23
  }
24
24
  checks.push({
25
- label: 'Claude command harness-init',
26
- status: cmdPath ? 'ok' : 'fail',
27
- detail: cmdPath ? `Found at ${cmdPath}` : 'Not installed',
25
+ label: 'Claude skill harness-init',
26
+ status: initSkillPath ? 'ok' : 'fail',
27
+ detail: initSkillPath ? `Found at ${initSkillPath}` : 'Not installed',
28
28
  fix: 'Run: harness-kit install',
29
29
  });
30
30
 
@@ -44,19 +44,19 @@ export default async function doctorAction() {
44
44
  fix: 'Run: harness-kit install',
45
45
  });
46
46
 
47
- // Check 3: Claude command harness-update-spec (check both scopes)
48
- let updateSpecPath = null;
49
- const globalUpdateSpec = resolveTargetPath('commands/harness-update-spec.md', 'global');
50
- const localUpdateSpec = resolveTargetPath('commands/harness-update-spec.md', 'local');
51
- if (await fs.pathExists(globalUpdateSpec)) {
52
- updateSpecPath = globalUpdateSpec;
53
- } else if (await fs.pathExists(localUpdateSpec)) {
54
- updateSpecPath = localUpdateSpec;
47
+ // Check 3: Claude skill harness-update-spec (check both scopes)
48
+ let updateSpecSkillPath = null;
49
+ const globalUpdateSpecSkill = resolveTargetPath('skills/harness-update-spec/SKILL.md', 'global');
50
+ const localUpdateSpecSkill = resolveTargetPath('skills/harness-update-spec/SKILL.md', 'local');
51
+ if (await fs.pathExists(globalUpdateSpecSkill)) {
52
+ updateSpecSkillPath = globalUpdateSpecSkill;
53
+ } else if (await fs.pathExists(localUpdateSpecSkill)) {
54
+ updateSpecSkillPath = localUpdateSpecSkill;
55
55
  }
56
56
  checks.push({
57
- label: 'Claude command harness-update-spec',
58
- status: updateSpecPath ? 'ok' : 'fail',
59
- detail: updateSpecPath ? `Found at ${updateSpecPath}` : 'Not installed',
57
+ label: 'Claude skill harness-update-spec',
58
+ status: updateSpecSkillPath ? 'ok' : 'fail',
59
+ detail: updateSpecSkillPath ? `Found at ${updateSpecSkillPath}` : 'Not installed',
60
60
  fix: 'Run: harness-kit install',
61
61
  });
62
62
 
@@ -109,7 +109,7 @@ export default async function doctorAction() {
109
109
  label: '.harness/',
110
110
  status: harnessExists ? 'ok' : 'fail',
111
111
  detail: harnessExists ? 'Project initialized' : 'Not found',
112
- fix: 'Run: /harness-init in Claude',
112
+ fix: 'Ask Claude to use the harness-init skill',
113
113
  });
114
114
 
115
115
  // Check 8: .comet.yaml
@@ -119,7 +119,7 @@ export default async function doctorAction() {
119
119
  label: '.comet.yaml',
120
120
  status: cometYamlExists ? 'ok' : 'fail',
121
121
  detail: cometYamlExists ? 'Found' : 'Not found',
122
- fix: 'Run: /harness-init in Claude or comet init',
122
+ fix: 'Ask Claude to use the harness-init skill or run comet init',
123
123
  });
124
124
 
125
125
  // Check 8: openspec/
@@ -25,7 +25,7 @@ export default async function installAction(options) {
25
25
  await ensureClaudeDirs(claudeDir);
26
26
 
27
27
  // Step 2: Copy files
28
- console.log(chalk.bold('Installing commands and skills:'));
28
+ console.log(chalk.bold('Installing skills:'));
29
29
  const fileResults = [];
30
30
 
31
31
  for (const mapping of FILE_MAPPINGS) {
@@ -113,5 +113,5 @@ export default async function installAction(options) {
113
113
  // Step 6: Summary
114
114
  console.log(chalk.bold.green('\n✅ Installation complete!\n'));
115
115
  console.log('Next step:');
116
- console.log(chalk.cyan(' Open Claude and run /harness-init to initialize your project\n'));
116
+ console.log(chalk.cyan(' Open Claude and ask it to use the harness-init skill to initialize your project\n'));
117
117
  }
@@ -10,12 +10,12 @@ export const PACKAGE_ROOT = path.resolve(__dirname, '..', '..');
10
10
 
11
11
  export const FILE_MAPPINGS = [
12
12
  {
13
- source: 'commands/harness-init.md',
14
- target: 'commands/harness-init.md',
13
+ source: 'skills/harness-init',
14
+ target: 'skills/harness-init',
15
15
  },
16
16
  {
17
- source: 'commands/harness-update-spec.md',
18
- target: 'commands/harness-update-spec.md',
17
+ source: 'skills/harness-update-spec',
18
+ target: 'skills/harness-update-spec',
19
19
  },
20
20
  {
21
21
  source: 'skills/md-to-html-doc.md',
@@ -33,10 +33,54 @@ export function resolveTargetPath(relativeTarget, scope = 'global') {
33
33
  }
34
34
 
35
35
  export async function hashFile(filePath) {
36
+ const stat = await fs.stat(filePath);
37
+
38
+ if (stat.isDirectory()) {
39
+ const hash = createHash('sha256');
40
+ await hashDirectoryInto(hash, filePath, filePath);
41
+ return hash.digest('hex').slice(0, 12);
42
+ }
43
+
36
44
  const content = await fs.readFile(filePath);
37
45
  return createHash('sha256').update(content).digest('hex').slice(0, 12);
38
46
  }
39
47
 
48
+ async function hashDirectoryInto(hash, rootDir, currentDir) {
49
+ const entries = await fs.readdir(currentDir);
50
+ entries.sort();
51
+
52
+ for (const entry of entries) {
53
+ const fullPath = path.join(currentDir, entry);
54
+ const stat = await fs.stat(fullPath);
55
+ const relativePath = path.relative(rootDir, fullPath).replaceAll('\\', '/');
56
+
57
+ hash.update(relativePath);
58
+ hash.update(stat.isDirectory() ? 'dir' : 'file');
59
+
60
+ if (stat.isDirectory()) {
61
+ await hashDirectoryInto(hash, rootDir, fullPath);
62
+ continue;
63
+ }
64
+
65
+ const content = await fs.readFile(fullPath);
66
+ hash.update(content);
67
+ }
68
+ }
69
+
70
+ async function getPathSize(targetPath) {
71
+ const stat = await fs.stat(targetPath);
72
+ if (stat.isFile()) {
73
+ return stat.size;
74
+ }
75
+
76
+ let total = 0;
77
+ const entries = await fs.readdir(targetPath);
78
+ for (const entry of entries) {
79
+ total += await getPathSize(path.join(targetPath, entry));
80
+ }
81
+ return total;
82
+ }
83
+
40
84
  export function getRecordPath(scope = 'global') {
41
85
  const claudeDir = resolveClaudeConfigDir({ scope });
42
86
  return path.join(claudeDir, 'harness-kit.json');
@@ -72,13 +116,12 @@ export async function copyFileRecord(sourceRel, targetRel, { force = false, scop
72
116
  await ensureClaudeDirs(claudeDir);
73
117
  await fs.copy(src, tgt, { overwrite: true });
74
118
  const hash = await hashFile(tgt);
75
- const stat = await fs.stat(tgt);
76
119
 
77
120
  return {
78
121
  target: tgt,
79
122
  didUpdate: true,
80
123
  hash,
81
- size: stat.size,
124
+ size: await getPathSize(tgt),
82
125
  };
83
126
  }
84
127
 
@@ -1,115 +0,0 @@
1
- ---
2
- name: harness-init
3
- description: Initialize .harness/ AI Engineering Harness directory structure, inject actual project code knowledge
4
- ---
5
-
6
- # Harness Init
7
-
8
- Based on the latest code on the current branch, initialize the corresponding files according to the directory structure below.
9
-
10
- **Core Principles (strictly follow):**
11
- 1. **Don't record what code can derive**: Information the AI can derive directly from source code (class names, method signatures, simple logic) should not be recorded
12
- 2. **Split high-cost derivation info by type**: Project identity goes to `index/project-profile.md`, data flow/message flow and external system runtime semantics (DB/QMQ/RPC/translation service/lock/CAT/Shark) go to `guides/backend.md`, high-risk chains go to `rules/architecture.md`
13
- 3. **Undervable content goes to decisions**: Design decisions, historical reasons, trade-offs (why use magic numbers, why dual type system) go into `decisions/`
14
- 4. **Human-readable content in human-docs/**: onboarding, architecture intro, operation manuals — generate md first, convert to HTML, then delete the md
15
- 5. **Don't hardcode non-existent content**: Must derive from real project code, don't fabricate
16
-
17
- **Target Directory Structure:**
18
-
19
- ```
20
- .harness/
21
-
22
- ├── README.md
23
- │ # Harness usage: principles, lifecycle, injection strategy
24
-
25
- ├── index/
26
- │ ├── routing.md
27
- │ │ # Task/phase/module → which context to inject (most important, decides context routing)
28
- │ ├── priority.md
29
- │ │ # Injection priority and intensity: MUST / SHOULD / HINT
30
- │ ├── module-map.md
31
- │ │ # Module → rules/domain/guides/memory mapping
32
- │ └── project-profile.md
33
- │ # Project identity card: app id, purpose, tech stack, runtime, key entry points, constants
34
-
35
- ├── rules/
36
- │ ├── architecture.md
37
- │ │ # Architecture constraints: dependency direction, module boundaries, Ownership, high-risk chains, prohibited cross-domain behavior
38
- │ ├── coding.md
39
- │ │ # Coding standards: naming, annotations, serialization, distributed locks
40
- │ ├── testing.md
41
- │ │ # Test rules: framework, file matching, strategy, fast test commands
42
- │ └── security.md
43
- │ # Security constraints: data security, SQL security, concurrency security, external call security
44
-
45
- ├── domain/
46
- │ ├── glossary.md
47
- │ │ # Domain terminology: core concepts, POI types, category IDs
48
- │ ├── business-rules.md
49
- │ │ # Long-term business rules
50
- │ └── runtime-semantics.md
51
- │ # Business semantics, state transitions, magic values, runtime rules
52
-
53
- ├── decisions/
54
- │ ├── adr/
55
- │ │ # Architecture Decision Records
56
- │ └── tradeoffs.md
57
- │ # Design tradeoffs: why designed this way, why not change casually
58
-
59
- ├── guides/
60
- │ ├── backend.md
61
- │ │ # AI execution manual: external system runtime semantics, message flow, new Service/Consumer/Producer, distributed locks, transactions
62
- │ └── ops.md
63
- │ # Operations manual: startup modes, logs, builds, config, monitoring, troubleshooting
64
-
65
- ├── memory/
66
- │ ├── pitfalls.md
67
- │ │ # Historical pitfall experiences
68
- │ ├── regressions.md
69
- │ │ # Historical regression issues
70
- │ ├── patterns.md
71
- │ │ # Reusable engineering patterns
72
- │ └── lessons.md
73
- │ # Long-term experience summary
74
-
75
- └── human-docs/
76
- ├── onboarding.html
77
- │ # Newcomer onboarding (for humans, not injected to AI)
78
- ├── architecture-intro.html
79
- │ # Architecture intro for humans (not injected to AI)
80
- └── operation-manual.html
81
- # Operation manual for humans (not injected to AI)
82
- ```
83
-
84
- **Content Split Rules:**
85
-
86
- | Information Type | Location | Reason |
87
- |---|---|---|
88
- | Project identity (app id, tech stack, module structure, key constants) | `index/project-profile.md` | High-frequency access, quick project overview |
89
- | Data flow/message flow (QMQ Topic, consumption chains) | `guides/backend.md` | Reference when developing new features |
90
- | External system runtime semantics (DB/QMQ/RPC/translation/lock/CAT/Shark) | `guides/backend.md` | Integration knowledge needed for coding |
91
- | ops (startup, logs, build, config, monitoring, troubleshooting) | `guides/ops.md` | Operations and publishing |
92
- | High-risk chains | `rules/architecture.md` | Part of architecture constraints |
93
- | Module boundaries/Ownership/prohibited cross-domain | `rules/architecture.md` | Part of architecture constraints |
94
- | Design decisions/tradeoffs | `decisions/` | Understanding "why designed this way" |
95
-
96
- **Exploration Strategy:**
97
-
98
- 1. Read project metadata: package.json/pom.xml (module structure, dependencies, versions), README.md, AGENTS.md
99
- 2. Identify tech stack: framework versions, RPC mode, database, message queue, cache
100
- 3. Map module boundaries: each module's responsibilities, dependency directions, prohibited behaviors
101
- 4. Deep dive into key code:
102
- - Service entry points
103
- - Entity definitions
104
- - Consumer/Producer (message flow, Topic, serialization mode)
105
- - Enums and state machines
106
- - Config files (databases, external services, feature flags)
107
- - Test structure
108
- 5. Check git history: recent commits, fix records, regressions
109
-
110
- **Execution Steps:**
111
-
112
- 1. Thoroughly explore the project's real structure (at least 3 rounds: tech stack → modules → data flow/message flow). If codegraph MCP is available, prefer using it.
113
- 2. Create all `.harness/` directories and files based on actual code content, split info by content rules
114
- 3. For `human-docs/`, write `.md` first, then call `md-to-html-doc` skill to convert to `.html`, then delete `.md`
115
- 4. After completion, verify directory structure is complete
@@ -1,122 +0,0 @@
1
- ---
2
- name: harness-update-spec
3
- description: Analyze current project state and derive whether .harness/ specs need updating, provide interactive suggestions
4
- ---
5
-
6
- # Harness Update Spec
7
-
8
- 基于当前项目最新代码状态,分析 `.harness/` 目录中的 spec 是否需要更新或新增。
9
-
10
- **核心原则(严格遵守)**:
11
- 1. **对比驱动**:以 `.harness/` 现有内容为基准,对比当前代码真实状态
12
- 2. **增量更新**:只关注"什么变了"和"什么缺失了",不重新生成全部内容
13
- 3. **交互式建议**:列出变更候选项,用户确认后逐个执行
14
- 4. **不记录可推导信息**:AI 能从源码直接推导的信息不写入 spec
15
-
16
- ## 分析流程
17
-
18
- ### 第一步:扫描现有 .harness/ 内容
19
-
20
- 读取当前 `.harness/` 目录下的所有文件,建立内容索引:
21
- - 每个文件的主题、关键声明、版本号(如有)
22
- - 识别出哪些 spec 存在、哪些缺失
23
-
24
- ### 第二步:探索项目当前状态
25
-
26
- 至少 3 轮深入探索(如果存在 codegraph 则优先使用 codegraph MCP):
27
-
28
- 1. **技术栈变更**:package.json/pom.xml 的依赖新增/删除/升级
29
- 2. **模块边界变更**:新增/删除/重构的模块、服务入口、实体
30
- 3. **数据流/消息流变更**:新的 Consumer/Producer、RPC 调用、Topic
31
- 4. **高风险链路变更**:新的分布式锁、事务、外部集成
32
- 5. **Git 近期变更**:最近 commit message 中暗示的架构调整
33
-
34
- ### 第三步:推导差异矩阵
35
-
36
- | 变更类型 | 影响 spec | 推导信号 |
37
- |---|---|---|
38
- | 新依赖 | `index/project-profile.md` | package.json/pom.xml 新增重要依赖 |
39
- | 新模块 | `index/module-map.md` | 新目录/新 Maven module |
40
- | 新服务入口 | `guides/backend.md` | 新 Consumer/Producer/Service |
41
- | 新 RPC/DB/QMQ 集成 | `guides/backend.md` | 新配置、新 Topic、新 Entity |
42
- | 新枚举/状态 | `domain/runtime-semantics.md` | 新增枚举类、状态定义 |
43
- | 架构变更 | `rules/architecture.md` | 模块间依赖方向变化 |
44
- | 新设计决策 | `decisions/tradeoffs.md` | commit message 中的权衡记录 |
45
- | 新项目身份 | `index/project-profile.md` | 应用号、环境、关键常量变更 |
46
- | 新业务术语 | `domain/glossary.md` | 新增领域概念 |
47
- | 新项目业务规则 | `domain/business-rules.md` | 新的长期业务逻辑 |
48
- | 新踩坑经验 | `memory/pitfalls.md` | 近期修复的问题 |
49
- | 新回归问题 | `memory/regressions.md` | 回归修复记录 |
50
- | 新模式 | `memory/patterns.md` | 可复用的新代码模式 |
51
-
52
- ### 第四步:交互式建议
53
-
54
- 以表格形式列出所有候选更新项:
55
-
56
- ```
57
- 🔍 harness-update-spec 分析报告
58
-
59
- 发现的变更(5 项):
60
-
61
- # 类型 影响 spec 信号
62
- ─── ───────── ────────────────────────────────── ──────────────────────
63
- 1 新增 guides/backend.md 新增 QMQ Topic: order.create
64
- 2 变更 index/project-profile.md 新增依赖: @elastic/elasticsearch v8.x
65
- 3 缺失 domain/runtime-semantics.md 存在 OrderState 枚举但未记录
66
- 4 变更 rules/architecture.md module-a 开始依赖 module-c
67
- 5 新增 memory/pitfalls.md 修复了分布式锁超时问题 (#1234)
68
-
69
- 缺失的 spec(2 项):
70
- ~ decisions/tradeoffs.md 不存在,可能有新设计决策
71
- ~ memory/patterns.md 不存在,可能有新模式
72
-
73
- 请选择要执行的操作:
74
- A. 全部更新
75
- B. 交互式选择(逐项确认)
76
- C. 取消
77
-
78
- 输入 [A/B/C]:
79
- ```
80
-
81
- ### 第五步:执行更新
82
-
83
- 根据用户选择执行:
84
-
85
- **A. 全部更新**:
86
- - 逐个生成/更新对应 spec 文件
87
- - 遵循内容拆分规则
88
- - 完成后用 `find .harness -type f | sort` 验证
89
-
90
- **B. 交互式选择**:
91
- - 逐项列出变更
92
- - 每次询问用户是否更新该项
93
- - 用户确认后执行该项更新
94
-
95
- **C. 取消**:
96
- - 打印摘要后退出
97
-
98
- ### 第六步:human-docs 处理
99
-
100
- 如果新增了 human-docs/ 下的内容:
101
- 1. 先写 `.md` 文件
102
- 2. 调用 `md-to-html-doc` skill 转 `.html`
103
- 3. 删除 `.md` 原文件
104
-
105
- ## 内容拆分规则(复用 harness-init)
106
-
107
- | 信息类型 | 存放位置 |
108
- |---|---|
109
- | 项目身份(应用号、技术栈、模块结构、关键常量) | `index/project-profile.md` |
110
- | 数据流/消息流(QMQ Topic、消费链路) | `guides/backend.md` |
111
- | 外部系统运行语义(DB/QMQ/RPC/翻译服务/锁/CAT/Shark) | `guides/backend.md` |
112
- | 高风险链路 | `rules/architecture.md` |
113
- | 模块边界/Ownership/禁止跨域行为 | `rules/architecture.md` |
114
- | 设计决策/权衡 | `decisions/` |
115
- | 历史踩坑/回归/模式 | `memory/` |
116
-
117
- ## 更新时的注意事项
118
-
119
- - **不要覆盖已有的正确内容**:只新增和变更部分
120
- - **保留历史记录**:如果是 ADR 或 memory 类 spec,追加而非覆盖
121
- - **验证一致性**:更新后检查 `.harness/` 内部引用是否一致
122
- - **如果 .harness/ 不存在**:提示用户先运行 `/harness-init`