create-harness-vibe-coding 0.8.0 → 0.8.2

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.
Files changed (37) hide show
  1. package/README-CN.md +40 -24
  2. package/README.md +44 -20
  3. package/package.json +1 -1
  4. package/src/generator.js +1 -1
  5. package/src/index.js +211 -11
  6. package/src/prompts.js +1 -1
  7. package/templates/common/.claude/agents/tdd-guide.md +55 -0
  8. package/templates/common/.claude/settings.json +22 -0
  9. package/templates/common/.claude/skills/tdd/SKILL.md +30 -0
  10. package/templates/common/.claude/skills/wf-auto/SKILL.md +107 -0
  11. package/templates/common/.claude/skills/wf-auto-spark/SKILL.md +39 -0
  12. package/templates/common/.claude/skills/wf-max/SKILL.md +10 -2
  13. package/templates/common/.claude/skills/wf-remove/SKILL.md +12 -5
  14. package/templates/common/.claude/skills/wf-update/SKILL.md +12 -5
  15. package/templates/common/.codex/hooks.json +59 -37
  16. package/templates/common/.harness-version +48 -25
  17. package/templates/common/AGENTS.md +5 -5
  18. package/templates/common/CLAUDE.md +12 -17
  19. package/templates/common/Harness/ECC-GUIDE.md +246 -0
  20. package/templates/common/Harness/README.md +129 -130
  21. package/templates/common/Harness/TDD-GUIDE.md +83 -0
  22. package/templates/common/Harness/WF-AUTO-SPARK.md +297 -0
  23. package/templates/common/Harness/WF-AUTO.md +508 -0
  24. package/templates/common/Harness/WF-MAX.md +24 -0
  25. package/templates/common/Harness/context-loading.md +38 -1
  26. package/templates/common/Harness/dispatch.md +40 -40
  27. package/templates/common/Harness/subagents.md +7 -21
  28. package/templates/common/Harness/tasks/_template/NAMING.md +47 -0
  29. package/templates/common/MEMORY.md +73 -66
  30. package/templates/common/SETUP.md +98 -63
  31. package/templates/common/scripts/validate-harness.mjs +92 -58
  32. package/templates/common/scripts/wf-mode-hook.mjs +895 -318
  33. package/templates/common/scripts/wf-remove.mjs +301 -81
  34. package/templates/common/scripts/wf-statusline.ps1 +62 -38
  35. package/templates/common/scripts/wf-statusline.sh +67 -48
  36. package/templates/common/scripts/wf-update-check.mjs +179 -81
  37. package/templates/optional/catalog.json +5 -5
package/README-CN.md CHANGED
@@ -15,9 +15,11 @@ npx create-harness-vibe-coding@latest my-project
15
15
  已有项目时,不要让 agent 猜。把这句话贴给它:
16
16
 
17
17
  ```text
18
- 请按照 https://github.com/zingspark/create-harness-vibe-coding 的 README 为当前项目配置 create-harness-vibe-coding;编辑前先扫描项目根目录并询问 Agent-link 安装前置问题;如果 Harness/ 已存在,先询问如何处理再写文件;新项目走 0-1 bootstrap,老项目或老架构升级先 dry-run,保留现有文件,只合并缺失的 Harness 规范,然后遵循 Harness/SETUP.md
18
+ 请完整阅读并严格遵循 https://github.com/zingspark/create-harness-vibe-coding,为当前项目配置 create-harness-vibe-coding。
19
19
  ```
20
20
 
21
+ 复杂规则不塞进这句话里。README 和生成后的 `Harness/SETUP.md` 才是安装、升级、合并和可选能力选择的准则。
22
+
21
23
  ## 你会得到什么
22
24
 
23
25
  | 文件/能力 | 作用 |
@@ -25,8 +27,8 @@ npx create-harness-vibe-coding@latest my-project
25
27
  | `CLAUDE.md` + `AGENTS.md` | 根目录 agent 入口 |
26
28
  | `Harness/README.md` | Harness 路由器 |
27
29
  | `Harness/tasks/` + `Harness/PROGRESS.md` | 跨会话任务状态 |
28
- | `.claude/skills/` | Claude Code workflow skill 入口 |
29
- | `.agents/skills/` | Codex repo skill 入口 |
30
+ | `.claude/skills/` | Claude Code workflow skill 入口 |
31
+ | `.agents/skills/` | Codex repo skill 入口 |
30
32
  | `.codex/` | Codex hooks/config |
31
33
  | `/wf` / `$wf` | 长任务 workflow |
32
34
  | `/wf-max` / `$wf-max` | 最大并行 workflow |
@@ -41,29 +43,31 @@ Claude Code 和 Codex 共用同一套核心 Harness 文档,但发现入口不
41
43
  - Codex:`.agents/skills/<name>/SKILL.md`,通常用 `$wf` 或 `/skills` 调用。
42
44
  - `.codex/` 只放 Codex 配置和 hooks;不要再使用根目录 `commands/*.toml` 伪装 Codex slash command。
43
45
 
44
- ## 新项目
46
+ ## 安装或升级路径
45
47
 
46
- ```bash
47
- npx create-harness-vibe-coding@latest my-project
48
- cd my-project
49
- ```
48
+ 写文件前,agent 必须先判断当前项目属于哪一种:
50
49
 
51
- 然后让 agent 执行:
50
+ | 项目状态 | 必须怎么做 |
51
+ |---|---|
52
+ | 空项目或新项目 | 运行脚手架,然后遵循 `Harness/SETUP.md` 做 0-1 bootstrap |
53
+ | 已有项目,没有 `Harness/` | 先扫描项目事实,先 `--dry-run`,保留现有文件,只合并缺失的 Harness 指南 |
54
+ | 老项目或老架构迁移 | 现有代码和文档是事实来源,先 dry-run,再用 `Harness/SETUP.md` 从事实中补 PRD、研究、架构和任务计划 |
55
+ | 已经有 `Harness/` | 不要把 `npx` 当更新器;先问用户是运行 `/wf-update` / `$wf-update` / `node Harness/scripts/wf-update-check.mjs`,保持不动,还是批准后移除重装 |
52
56
 
53
- ```text
54
- 读 Harness/SETUP.md。把这个项目从想法引导到第一个 vertical slice。
55
- ```
57
+ 根目录扫描必须包括:顶层文件、`CLAUDE.md`、`AGENTS.md`、`.claude/`、`.agents/`、`.codex/`、`Harness/`、package 文件、CI 文件、应用入口、测试/构建命令、已有文档、已经安装的 skills/plugins/rules。推荐可选能力前,必须先排除已经安装的能力,避免重复推荐。
56
58
 
57
59
  ## 已有项目安全合并
58
60
 
59
61
  ```bash
60
- # 先预览,不写文件
61
- npx create-harness-vibe-coding@latest my-app . -y --dry-run
62
+ # 先用机器可读预览,不写文件
63
+ npx create-harness-vibe-coding@latest my-app . -y --dry-run --json
62
64
 
63
65
  # 只补缺失文件,不覆盖已有文件
64
- npx create-harness-vibe-coding@latest my-app . -y --on-conflict skip
66
+ npx create-harness-vibe-coding@latest my-app . -y --on-conflict skip --json
65
67
  ```
66
68
 
69
+ JSON 输出就是 agent 的安装报告:`scan` 代替手写根目录探测,`plan.create` 交给脚本处理,只有 `agent.aiMergeRequired` 里的文件需要 AI 语义比较和用户监督合并。除非这个列表里出现冲突文件,否则不要读取包源码或模板。
70
+
67
71
  `npx` 是安装和安全补缺入口,不是已安装 Harness 的同步更新器。项目里已经有 `Harness/` 后,Claude Code 用 `/wf-update`,Codex 用 `$wf-update`,或者直接运行:
68
72
 
69
73
  ```bash
@@ -90,33 +94,45 @@ npx create-harness-vibe-coding@latest my-app -y --recommend superpowers,codegrap
90
94
 
91
95
  本地 workflow:`browser-e2e`、`ui-ux-review`、`ts-react-frontend`、`python-backend`、`github-pr-review`。
92
96
 
93
- 外部建议只写入 `Harness/SETUP.md`,不会自动安装第三方技能:`superpowers`、`caveman`、`agent-research`、`codegraph`。
97
+ 外部建议只写入 `Harness/SETUP.md`,不会自动安装第三方技能:
98
+
99
+ | 建议 | 用途 | 链接 |
100
+ |---|---|---|
101
+ | `superpowers` | 社区 skill registry 和 agent workflow | <https://github.com/obra/Superpowers> |
102
+ | `caveman` | 简洁低 token 的 agent 行为和记忆压缩 | <https://github.com/JuliusBrussee/caveman> |
103
+ | `agent-research` | 文献、产品、依赖和生态研究类 agent skills | <https://github.com/lingzhi227/agent-research-skills> |
104
+ | `codegraph` | 代码图谱或仓库地图工具 | <https://github.com/colbymchenry/codegraph> |
105
+
106
+ 这些只是给用户 agent 自行评估的 GitHub 链接。脚手架不维护第三方安装步骤,只在确认项目尚未安装同类能力后记录用户选择。
94
107
 
95
108
  不加 `-y` 时,CLI 会提供 checkbox/multiselect 选择。
96
109
 
97
110
  ## Agent-link 安装前置问题
98
111
 
99
- Agent 必须先扫描根目录,再最多问 3 个阻塞问题。扫描要覆盖:
112
+ Agent 应先拿机器可读安装报告,再最多问 3 个阻塞问题:
100
113
 
101
- - `CLAUDE.md`、`AGENTS.md`
102
- - `.claude/`、`.agents/`、`.codex/`
103
- - `Harness/`
104
- - `README.md`
105
- - package 文件、CI 文件、已有文档目录、应用入口和测试命令
114
+ ```bash
115
+ npx create-harness-vibe-coding@latest my-app . -y --dry-run --json
116
+ ```
117
+
118
+ 使用 `scan.markers`,不要手写一串根目录探测命令。`plan.create` 由脚本处理;只有 `agent.aiMergeRequired` 里的文件需要 AI 比较并由用户监督合并。
106
119
 
107
120
  只在影响写入时提问:
108
121
 
109
122
  - 已有 `CLAUDE.md` 或 `AGENTS.md`:合并缺失 Harness 指南、保持不动,还是跳过?
110
123
  - 已有 `Harness/`:走 `/wf-update` / `$wf-update`、dry-run 补缺、保持不动,还是批准后移除重装?
111
- - 要启用哪些能力:本地 workflow,或只记录外部建议?
124
+ - 排除已安装能力后,还要启用哪些本地 workflow,或只记录哪些外部 GitHub 推荐链接?
112
125
 
113
126
  默认策略:保留已有文件,只补缺失内容。
114
127
 
115
128
  ## 验证
116
129
 
117
130
  ```bash
131
+ # 当前脚手架仓库
118
132
  npm test
119
- node Harness/scripts/validate-harness.mjs
133
+
134
+ # 生成后的项目完成 bootstrap 后
135
+ node Harness/scripts/validate-harness.mjs --strict
120
136
  ```
121
137
 
122
138
  ## 项目结构
package/README.md CHANGED
@@ -21,7 +21,7 @@ npx create-harness-vibe-coding@latest my-project
21
21
  Already have a project? **Don't read the docs**. Paste this sentence. Your agent handles the rest.
22
22
 
23
23
  ```text
24
- Follow the README at https://github.com/zingspark/create-harness-vibe-coding to configure this project with create-harness-vibe-coding; before editing, scan the project root and ask the Agent-link install intake questions; if Harness/ already exists, ask how to handle it before writing; for a new project run the 0-1 bootstrap, and for an existing project or legacy architecture run a dry-run first, preserve existing files, merge only missing Harness guidance, then follow Harness/SETUP.md.
24
+ Read and follow https://github.com/zingspark/create-harness-vibe-coding exactly to configure this project with create-harness-vibe-coding.
25
25
  ```
26
26
 
27
27
  That's it. Two paths into the harness — you type `npx`, or your agent reads the sentence.
@@ -104,16 +104,31 @@ cd my-project
104
104
  # Your agent reads Harness/SETUP.md. Done.
105
105
  ```
106
106
 
107
+ ### Install or Upgrade Path
108
+
109
+ Before writing, the agent must identify which path applies:
110
+
111
+ | Project state | Required action |
112
+ |---------------|-----------------|
113
+ | Empty or new project | Run the scaffold, then follow `Harness/SETUP.md` for 0-1 bootstrap |
114
+ | Existing project, no `Harness/` | Scan project facts first, run `--dry-run`, preserve existing files, merge only missing Harness guidance |
115
+ | Legacy architecture or older project docs | Treat existing code/docs as source of truth, dry-run first, then use `Harness/SETUP.md` to fill facts from observed project reality |
116
+ | Existing `Harness/` | Do not use `npx` as an updater; ask whether to run `/wf-update`, `$wf-update`, `node Harness/scripts/wf-update-check.mjs`, keep untouched, or remove/reinstall after approval |
117
+
118
+ Root scan must include top-level files, `CLAUDE.md`, `AGENTS.md`, `.claude/`, `.agents/`, `.codex/`, `Harness/`, package files, CI files, app entry points, test/build commands, existing docs, and already-installed skills/plugins/rules. Use that scan before recommending optional capabilities so you do not suggest duplicates.
119
+
107
120
  ### Existing project — safe merge
108
121
 
109
122
  ```bash
110
- # Preview first. Always.
111
- npx create-harness-vibe-coding@latest my-app . -y --dry-run
112
-
123
+ # Machine-readable preview first. Always.
124
+ npx create-harness-vibe-coding@latest my-app . -y --dry-run --json
125
+
113
126
  # Add only what's missing. Never overwrite.
114
- npx create-harness-vibe-coding@latest my-app . -y --on-conflict skip
127
+ npx create-harness-vibe-coding@latest my-app . -y --on-conflict skip --json
115
128
  ```
116
129
 
130
+ The JSON output is the agent's install report: `scan` replaces hand-written root probes, `plan.create` is script-owned, and `agent.aiMergeRequired` is the only list that needs semantic AI review. Do not read package source or templates unless `agent.aiMergeRequired` names a conflicting file.
131
+
117
132
  `npx` is an install and safe-merge entry, not an update engine for an already installed Harness. Once `Harness/` exists, use `/wf-update` in Claude Code, `$wf-update` in Codex, or `node Harness/scripts/wf-update-check.mjs`; root entry conflicts such as `CLAUDE.md`, `AGENTS.md`, `.claude/`, `.agents/`, `.codex/`, and local Harness docs need agent-mediated merge decisions.
118
133
 
119
134
  | Flag | Does |
@@ -148,24 +163,30 @@ npx create-harness-vibe-coding@latest my-app -y --recommend superpowers,codegrap
148
163
 
149
164
  External recommendations are recorded in `Harness/SETUP.md` but not installed automatically:
150
165
 
151
- | Recommendation | For |
152
- |----------------|-----|
153
- | `superpowers` | Community skill registry and agent workflows |
154
- | `caveman` | Strict low-abstraction workflow/style capability |
155
- | `agent-research` | Broader product, dependency, and ecosystem research agents |
156
- | `codegraph` | Code graph or repository-map tooling |
166
+ | Recommendation | For | Source |
167
+ |----------------|-----|--------|
168
+ | `superpowers` | Community skill registry and agent workflows | <https://github.com/obra/Superpowers> |
169
+ | `caveman` | Terse, low-token agent behavior and memory compression | <https://github.com/JuliusBrussee/caveman> |
170
+ | `agent-research` | Research-agent skills for literature, product, dependency, and ecosystem investigation | <https://github.com/lingzhi227/agent-research-skills> |
171
+ | `codegraph` | Code graph or repository-map tooling | <https://github.com/colbymchenry/codegraph> |
172
+
173
+ These are links for the user's agent to evaluate. The scaffold does not maintain third-party install steps; it only records selected recommendations after checking what is already installed.
157
174
 
158
175
  ### Agent-link intake
159
176
 
160
- When your agent reads the one-sentence prompt above, it must first scan the project root, then ask **at most 3 blocking questions** before touching files.
177
+ When your agent reads the one-sentence prompt above, it should get the machine-readable install report before asking broad questions:
178
+
179
+ ```bash
180
+ npx create-harness-vibe-coding@latest my-app . -y --dry-run --json
181
+ ```
161
182
 
162
- Root scan checklist: list top-level files, detect `CLAUDE.md`, `AGENTS.md`, `.claude/`, `.agents/`, `.codex/`, `Harness/`, package files, CI files, docs folders, and obvious app entry points.
183
+ Use `scan.markers` instead of manual top-level probes. Ask **at most 3 blocking questions** before touching files. Files in `plan.create` are handled by the script; only files in `agent.aiMergeRequired` need AI comparison and user-supervised merge decisions.
163
184
 
164
185
  Ask these only when they affect writes:
165
186
 
166
187
  - If `CLAUDE.md` or `AGENTS.md` already exists, should missing Harness guidance be merged, kept separate, or skipped?
167
188
  - If `Harness/` already exists, should the agent run update/dry-run, merge missing files, keep it untouched, or remove/reinstall after approval?
168
- - Which optional capabilities should be enabled: local workflows (`browser-e2e`, `ui-ux-review`, `ts-react-frontend`, `python-backend`, `github-pr-review`) and recommendation-only external options (`Superpowers`, `Caveman`, `agent research`, `code graph`)?
189
+ - Which optional capabilities should be enabled, after excluding capabilities already installed: local workflows (`browser-e2e`, `ui-ux-review`, `ts-react-frontend`, `python-backend`, `github-pr-review`) and recommendation-only external links (`Superpowers`, `Caveman`, `agent research`, `code graph`)?
169
190
 
170
191
  Harness docs always live in root `Harness/`; do not route Harness files through `docs/`. If a file already exists, the agent asks first. The default is always **preserve**.
171
192
 
@@ -178,12 +199,15 @@ Harness docs always live in root `Harness/`; do not route Harness files through
178
199
  "/wf-update" or "$wf-update" # pull latest harness improvements
179
200
  ```
180
201
 
181
- ### Verify
182
-
183
- ```bash
184
- npm test
185
- node Harness/scripts/validate-harness.mjs
186
- ```
202
+ ### Verify
203
+
204
+ ```bash
205
+ # In this package repo
206
+ npm test
207
+
208
+ # In a generated project after bootstrap
209
+ node Harness/scripts/validate-harness.mjs --strict
210
+ ```
187
211
 
188
212
  ---
189
213
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-harness-vibe-coding",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "Scaffold a 0-1 product harness for AI-assisted research, PRD, planning, architecture, build, test, and feedback loops",
5
5
  "type": "module",
6
6
  "bin": {
package/src/generator.js CHANGED
@@ -377,7 +377,7 @@ function registerExternalRecommendations(file, content, selectedRecommendations)
377
377
  if (!selectedRecommendations.length || file !== 'Harness/SETUP.md') return content;
378
378
 
379
379
  const lines = selectedRecommendations.map(item => (
380
- `- \`${item.id}\` - ${item.description} Recommendation only; not installed by this scaffold. Use the discovery/install hint: ${item.installHint}`
380
+ `- \`${item.id}\` - ${item.description} Recommendation only; not installed by this scaffold. Source: ${item.url}`
381
381
  ));
382
382
 
383
383
  return `${content.trimEnd()}\n\n## Selected External Recommendations\n\n${lines.join('\n')}\n`;
package/src/index.js CHANGED
@@ -81,11 +81,19 @@ const generationOptions = {
81
81
  const DEFAULT_NAME = 'my-vibe-project';
82
82
 
83
83
  // --json: machine-readable output, no prompts, no decorative output
84
- if (generationOptions.json) {
85
- const projectName = argName || DEFAULT_NAME;
86
- const targetDir = argDir || `./${projectName}`;
87
- const result = generate({ projectName, targetDir, ...generationOptions });
88
- printJsonResult(result);
84
+ if (generationOptions.json) {
85
+ const projectName = argName || DEFAULT_NAME;
86
+ const targetDir = argDir || `./${projectName}`;
87
+ const scan = scanTarget(targetDir);
88
+ const result = generate({ projectName, targetDir, ...generationOptions });
89
+ result.scan = createJsonScan(scan);
90
+ result.agent = createAgentGuidance(result, {
91
+ projectName,
92
+ targetDir,
93
+ options: generationOptions,
94
+ scan,
95
+ });
96
+ printJsonResult(result);
89
97
  // printJsonResult exits with 1 on failure; we only reach here on success
90
98
  process.exit(0);
91
99
  }
@@ -377,7 +385,7 @@ function printOptions() {
377
385
  console.log('');
378
386
  console.log(pc.bold('External recommendations:'));
379
387
  for (const item of catalog.externalRecommendations) {
380
- console.log(` ${pc.cyan(item.id)} - ${item.description} (${item.installMode})`);
388
+ console.log(` ${pc.cyan(item.id)} - ${item.description} (${item.installMode}) ${item.url || ''}`.trimEnd());
381
389
  }
382
390
  }
383
391
  console.log('');
@@ -429,6 +437,17 @@ function scanTarget(targetDir) {
429
437
  ? fs.readdirSync(resolvedDir)
430
438
  : [];
431
439
  const hasHarness = isDirectory && fs.existsSync(path.join(resolvedDir, 'Harness'));
440
+ const hasClaude = isDirectory && fs.existsSync(path.join(resolvedDir, 'CLAUDE.md'));
441
+ const hasAgents = isDirectory && fs.existsSync(path.join(resolvedDir, 'AGENTS.md'));
442
+ const hasAgentSkills = isDirectory && fs.existsSync(path.join(resolvedDir, '.agents'));
443
+ const hasCodex = isDirectory && fs.existsSync(path.join(resolvedDir, '.codex'));
444
+ const hasDocs = isDirectory && fs.existsSync(path.join(resolvedDir, 'docs'));
445
+ const hasReadme = isDirectory && fs.existsSync(path.join(resolvedDir, 'README.md'));
446
+ const hasPackageJson = isDirectory && fs.existsSync(path.join(resolvedDir, 'package.json'));
447
+ const hasPyproject = isDirectory && fs.existsSync(path.join(resolvedDir, 'pyproject.toml'));
448
+ const hasGoMod = isDirectory && fs.existsSync(path.join(resolvedDir, 'go.mod'));
449
+ const hasGithub = isDirectory && fs.existsSync(path.join(resolvedDir, '.github'));
450
+ const hasGitignore = isDirectory && fs.existsSync(path.join(resolvedDir, '.gitignore'));
432
451
 
433
452
  return {
434
453
  resolvedDir,
@@ -436,15 +455,196 @@ function scanTarget(targetDir) {
436
455
  isDirectory,
437
456
  entries,
438
457
  hasHarness,
439
- hasClaude: isDirectory && fs.existsSync(path.join(resolvedDir, 'CLAUDE.md')),
440
- hasAgents: isDirectory && fs.existsSync(path.join(resolvedDir, 'AGENTS.md')),
441
- hasAgentSkills: isDirectory && fs.existsSync(path.join(resolvedDir, '.agents')),
442
- hasCodex: isDirectory && fs.existsSync(path.join(resolvedDir, '.codex')),
443
- hasDocs: isDirectory && fs.existsSync(path.join(resolvedDir, 'docs')),
458
+ hasClaude,
459
+ hasAgents,
460
+ hasAgentSkills,
461
+ hasCodex,
462
+ hasDocs,
463
+ hasReadme,
464
+ hasPackageJson,
465
+ hasPyproject,
466
+ hasGoMod,
467
+ hasGithub,
468
+ hasGitignore,
444
469
  needsConflictPolicy: exists && (!isDirectory || entries.length > 0 || hasHarness),
445
470
  };
446
471
  }
447
472
 
473
+ function createJsonScan(scan) {
474
+ const topLevelEntries = scan.entries.slice(0, 50);
475
+
476
+ return {
477
+ resolvedDir: scan.resolvedDir,
478
+ exists: scan.exists,
479
+ isDirectory: scan.isDirectory,
480
+ entryCount: scan.entries.length,
481
+ topLevelEntries,
482
+ topLevelEntriesTruncated: scan.entries.length > topLevelEntries.length,
483
+ needsConflictPolicy: scan.needsConflictPolicy,
484
+ markers: {
485
+ hasHarness: scan.hasHarness,
486
+ hasClaude: scan.hasClaude,
487
+ hasAgents: scan.hasAgents,
488
+ hasAgentSkills: scan.hasAgentSkills,
489
+ hasCodex: scan.hasCodex,
490
+ hasDocs: scan.hasDocs,
491
+ hasReadme: scan.hasReadme,
492
+ hasPackageJson: scan.hasPackageJson,
493
+ hasPyproject: scan.hasPyproject,
494
+ hasGoMod: scan.hasGoMod,
495
+ hasGithub: scan.hasGithub,
496
+ hasGitignore: scan.hasGitignore,
497
+ },
498
+ };
499
+ }
500
+
501
+ function createAgentGuidance(result, { projectName, targetDir, options, scan }) {
502
+ const attentionFiles = [...new Set([
503
+ ...(result.plan?.conflict || []),
504
+ ...(result.plan?.skip || []),
505
+ ])].sort();
506
+ const aiMergeRequired = attentionFiles.map(file => createFileGuidance(file));
507
+ const hasBlockingConflicts = (result.plan?.conflict || []).length > 0;
508
+ const safeMergeCommand = commandFor(projectName, targetDir, {
509
+ ...options,
510
+ dryRun: false,
511
+ onConflict: 'skip',
512
+ json: true,
513
+ });
514
+ const previewCommand = commandFor(projectName, targetDir, {
515
+ ...options,
516
+ dryRun: true,
517
+ json: true,
518
+ });
519
+ const next = [];
520
+
521
+ if (scan.hasHarness) {
522
+ next.push({
523
+ action: 'stop',
524
+ reason: 'Harness already exists; use wf-update or Harness/scripts/wf-update-check.mjs instead of reinstalling blindly.',
525
+ });
526
+ } else if (result.dryRun && !hasBlockingConflicts) {
527
+ next.push({
528
+ action: 'install',
529
+ command: safeMergeCommand,
530
+ reason: 'Dry-run has no blocking conflicts; let the script create missing files.',
531
+ });
532
+ } else if (result.dryRun && hasBlockingConflicts) {
533
+ next.push({
534
+ action: 'safe-merge',
535
+ command: safeMergeCommand,
536
+ reason: 'Default dry-run found existing files; rerun with --on-conflict skip so the script creates missing files and preserves existing ones.',
537
+ });
538
+ } else if (result.success) {
539
+ next.push({
540
+ action: 'bootstrap',
541
+ command: 'Read Harness/SETUP.md and use this JSON plan before opening any package templates.',
542
+ reason: 'Scaffold files were written; bootstrap project facts from local evidence.',
543
+ });
544
+ } else {
545
+ next.push({
546
+ action: 'inspect-errors',
547
+ reason: 'Generation failed before safe scaffold output was available.',
548
+ });
549
+ }
550
+
551
+ if (aiMergeRequired.length > 0) {
552
+ next.push({
553
+ action: 'ai-merge',
554
+ files: aiMergeRequired.map(item => item.file),
555
+ reason: 'Only these existing/conflicting files need semantic review. Files in plan.create are script-owned.',
556
+ });
557
+ }
558
+
559
+ return {
560
+ sourceOfTruth: 'Use this JSON scan/plan first. Do not read package source or templates unless aiMergeRequired lists a file.',
561
+ previewCommand,
562
+ safeMergeCommand,
563
+ scriptHandled: {
564
+ create: result.plan?.create?.length || 0,
565
+ mkdir: result.plan?.mkdir?.length || 0,
566
+ backup: result.plan?.backup?.length || 0,
567
+ overwrite: result.plan?.overwrite?.length || 0,
568
+ },
569
+ aiMergeRequired,
570
+ next,
571
+ };
572
+ }
573
+
574
+ function createFileGuidance(file) {
575
+ const normalized = file.replace(/\\/g, '/');
576
+ const guidance = {
577
+ file: normalized,
578
+ templateHint: templateHintFor(normalized),
579
+ requiresUserConsent: false,
580
+ defaultAction: 'preserve',
581
+ reason: 'Existing file or path needs semantic review before any merge.',
582
+ };
583
+
584
+ if (normalized.endsWith('/')) {
585
+ return {
586
+ ...guidance,
587
+ templateHint: null,
588
+ defaultAction: 'stop',
589
+ reason: 'A file blocks a required scaffold directory. Stop and ask before moving or replacing it.',
590
+ };
591
+ }
592
+
593
+ if (normalized === 'CLAUDE.md' || normalized === 'AGENTS.md') {
594
+ return {
595
+ ...guidance,
596
+ requiresUserConsent: true,
597
+ reason: 'Root agent entry contract. Preserve project rules and ask before merging Harness startup guidance.',
598
+ };
599
+ }
600
+
601
+ if (normalized === 'README.md') {
602
+ return {
603
+ ...guidance,
604
+ reason: 'Project-owned public/development documentation. Preserve by default; append development notes only after review.',
605
+ };
606
+ }
607
+
608
+ if (normalized === 'Harness/README.md' || normalized === 'Harness/MEMORY.md') {
609
+ return {
610
+ ...guidance,
611
+ reason: 'Harness router/registry conflict. Merge only missing routing or registration entries.',
612
+ };
613
+ }
614
+
615
+ return guidance;
616
+ }
617
+
618
+ function templateHintFor(file) {
619
+ if (file === 'Harness/SETUP.md') return 'templates/common/SETUP.md';
620
+ return `templates/common/${file}`;
621
+ }
622
+
623
+ function commandFor(projectName, targetDir, options) {
624
+ const args = [
625
+ 'npx',
626
+ 'create-harness-vibe-coding@latest',
627
+ projectName,
628
+ targetDir,
629
+ '-y',
630
+ ];
631
+
632
+ if (options.dryRun) args.push('--dry-run');
633
+ if (options.onConflict) args.push('--on-conflict', options.onConflict);
634
+ if (options.withOptions?.length) args.push('--with', options.withOptions.join(','));
635
+ if (options.withoutOptions?.length) args.push('--without', options.withoutOptions.join(','));
636
+ if (options.externalOptions?.length) args.push('--recommend', options.externalOptions.join(','));
637
+ if (options.preset) args.push('--preset', options.preset);
638
+ if (options.json) args.push('--json');
639
+
640
+ return args.map(shellQuoteArg).join(' ');
641
+ }
642
+
643
+ function shellQuoteArg(arg) {
644
+ if (/^[A-Za-z0-9@._/\\:-]+$/.test(arg)) return arg;
645
+ return JSON.stringify(arg);
646
+ }
647
+
448
648
  function printScan(scan) {
449
649
  if (!scan.exists) return;
450
650
 
package/src/prompts.js CHANGED
@@ -73,7 +73,7 @@ export async function askOptionalSelections(catalog) {
73
73
  const externalOptions = (catalog.externalRecommendations || []).map(item => ({
74
74
  value: item.id,
75
75
  label: item.title,
76
- hint: `${item.description} Recommendation only.`,
76
+ hint: item.url ? `${item.description} ${item.url}` : `${item.description} Recommendation only.`,
77
77
  }));
78
78
 
79
79
  const selectedLocal = localOptions.length
@@ -0,0 +1,55 @@
1
+ ---
2
+ name: tdd-guide
3
+ description: Test-Driven Development specialist enforcing write-tests-first methodology. Use PROACTIVELY when writing new features, fixing bugs, or refactoring code. Ensures 80%+ test coverage.
4
+ tools: Read, Write, Edit, Bash, Grep, Glob
5
+ model: sonnet
6
+ ---
7
+
8
+ # TDD Guide Agent
9
+
10
+ Enforces TDD workflow. Load `Harness/TDD-GUIDE.md` first, then ECC testing rules for the project stack.
11
+
12
+ ## Inputs Required
13
+
14
+ - Task description and acceptance criteria from PLAN.md
15
+ - Current test coverage status
16
+ - Stack-specific testing tools (Jest, Pytest, Go test, etc.)
17
+
18
+ ## Workflow
19
+
20
+ 1. READ acceptance criteria
21
+ 2. WRITE failing test (RED)
22
+ 3. VERIFY test fails for expected reason
23
+ 4. Report test file path and expected failure to Implementer
24
+
25
+ Do NOT write implementation code. Only tests.
26
+
27
+ ## Allowed Write Set
28
+
29
+ - Test files only (`*.test.ts`, `*.test.tsx`, `test_*.py`, `*_test.go`, etc.)
30
+ - Test fixtures and mocks
31
+ - Test configuration files
32
+
33
+ ## Forbidden
34
+
35
+ - Production/source code changes
36
+ - Loosening existing test assertions
37
+ - Deleting existing tests without explicit approval
38
+
39
+ ## Verification
40
+
41
+ - Test MUST fail before handing off to Implementer
42
+ - Test MUST cover acceptance criteria + error paths
43
+ - Run `node Harness/scripts/validate-harness.mjs` after significant test additions
44
+
45
+ ## Return Format
46
+
47
+ ```text
48
+ Agent: tdd-guide
49
+ Task: <task-id>
50
+ Tests written: <file paths>
51
+ Coverage before: X%
52
+ Expected coverage after: Y%
53
+ Failing tests: <list of test names and expected failure reasons>
54
+ Next: Dispatch Implementer to make tests pass
55
+ ```
@@ -63,6 +63,28 @@
63
63
  }
64
64
  ]
65
65
  }
66
+ ],
67
+ "PostToolUse": [
68
+ {
69
+ "matcher": "",
70
+ "hooks": [
71
+ {
72
+ "type": "command",
73
+ "command": "node Harness/scripts/wf-mode-hook.mjs"
74
+ }
75
+ ]
76
+ }
77
+ ],
78
+ "Stop": [
79
+ {
80
+ "matcher": "",
81
+ "hooks": [
82
+ {
83
+ "type": "command",
84
+ "command": "node Harness/scripts/wf-mode-hook.mjs"
85
+ }
86
+ ]
87
+ }
66
88
  ]
67
89
  }
68
90
  }
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: tdd
3
+ description: Test-driven development. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration tests.
4
+ ---
5
+
6
+ # TDD Adapter
7
+
8
+ Thin tool adapter. Authoritative guide: `Harness/TDD-GUIDE.md`.
9
+
10
+ ## Invocation
11
+
12
+ - Claude Code: use `/tdd` or select the `tdd` skill.
13
+ - Codex CLI or IDE: use `$tdd` or `/skills` then choose `tdd`.
14
+
15
+ ## Load
16
+
17
+ 1. `Harness/TDD-GUIDE.md`
18
+ 2. ECC stack-specific testing rules (e.g., `typescript/testing.md`, `python/testing.md`)
19
+ 3. Current task `PLAN.md`
20
+
21
+ ## Rules
22
+
23
+ 1. **RED first**: Write failing test before ANY implementation code.
24
+ 2. **GREEN minimal**: Write only enough code to pass the test.
25
+ 3. **REFACTOR safe**: Improve code while keeping all tests green.
26
+ 4. **Coverage gate**: ≥80% before marking task complete.
27
+ 5. **Test names**: Describe behavior — `test('returns X when Y')`.
28
+ 6. **AAA structure**: Arrange → Act → Assert.
29
+ 7. **Error paths**: Test failure cases, not just happy path.
30
+ 8. **WF-MAX**: Test Writer agent dispatched BEFORE Implementer in every wave.