dev-harness-cli 1.0.5 → 1.2.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.
Files changed (45) hide show
  1. package/README.md +158 -230
  2. package/cli/commands/checkpoint.mjs +2 -2
  3. package/cli/commands/config.mjs +12 -12
  4. package/cli/commands/contract.mjs +10 -10
  5. package/cli/commands/detect-tool.mjs +5 -4
  6. package/cli/commands/init.mjs +10 -10
  7. package/cli/commands/learn.mjs +3 -3
  8. package/cli/commands/pause.mjs +1 -1
  9. package/cli/commands/phase.mjs +6 -6
  10. package/cli/commands/resume.mjs +3 -3
  11. package/cli/commands/rollback.mjs +9 -9
  12. package/cli/commands/set-mode.mjs +5 -5
  13. package/cli/commands/status.mjs +9 -9
  14. package/cli/commands/validate.mjs +7 -7
  15. package/cli/commands/worktree.mjs +6 -6
  16. package/cli/{harness-dev.mjs → dev-harness.mjs} +2 -2
  17. package/cli/lib/config-registry.mjs +2 -2
  18. package/cli/lib/contract.mjs +3 -3
  19. package/cli/lib/gates.mjs +11 -9
  20. package/cli/lib/help.mjs +28 -28
  21. package/cli/lib/paths.mjs +87 -8
  22. package/cli/lib/ralph-inner.mjs +2 -2
  23. package/cli/lib/ralph-outer.mjs +3 -3
  24. package/cli/lib/ralph-output.mjs +1 -1
  25. package/cli/lib/scaffold.mjs +18 -18
  26. package/cli/lib/state.mjs +1 -1
  27. package/cli/lib/templates.mjs +38 -1
  28. package/package.json +8 -4
  29. package/schema/feature-list.schema.json +63 -0
  30. package/templates/AGENTS.md +19 -15
  31. package/templates/ci/github-actions.yml +2 -2
  32. package/templates/ci/gitlab-ci.yml +2 -2
  33. package/templates/docs/agents/generator.md +1 -1
  34. package/templates/docs/agents/planner.md +1 -1
  35. package/templates/docs/agents/simplifier.md +1 -1
  36. package/templates/docs/phases/build.md +3 -3
  37. package/templates/docs/phases/define.md +3 -3
  38. package/templates/docs/phases/plan.md +3 -3
  39. package/templates/docs/phases/review.md +2 -2
  40. package/templates/docs/phases/ship.md +3 -3
  41. package/templates/docs/phases/simplify.md +3 -3
  42. package/templates/docs/phases/verify.md +2 -2
  43. package/templates/harness-config.json +42 -0
  44. package/templates/init.ps1 +1 -1
  45. package/templates/progress.md +18 -0
package/README.md CHANGED
@@ -1,298 +1,226 @@
1
+ <div align="center">
2
+
1
3
  # Dev Harness
2
4
 
3
- **Agent-agnostic development pipeline CLI.** Scaffold, phase orchestrate, gate validate, and iterate any software project — works with any coding agent (Claude Code, Codex, OpenCode, Cursor, etc.).
5
+ ### Agent-agnostic development pipeline CLI
6
+
7
+ Scaffold · Phase orchestration · Gate validation · Iteration
8
+
9
+ [![npm version](https://img.shields.io/npm/v/dev-harness-cli.svg)](https://www.npmjs.com/package/dev-harness-cli)
10
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
11
+ [![Node.js >=18](https://img.shields.io/badge/node-%3E%3D18-green.svg)](https://nodejs.org)
12
+ [![Zero Dependencies](https://img.shields.io/badge/dependencies-zero-blue.svg)](#)
13
+
14
+ **Works with any coding agent:** Claude Code · Codex · Cursor · Aider · Continue · OpenCode · Windsurf · Gemini · GitHub Copilot · Cline · Roo · Kilo Code · Amazon Q · and more
15
+
16
+ </div>
17
+
18
+ ---
19
+
20
+ ## What is this?
21
+
22
+ **Dev Harness** is a CLI tool that brings structure to AI-assisted software development. Instead of ad-hoc prompting, it enforces a **phase pipeline** with **gate validation** — ensuring specs are written before code, code is reviewed before shipping, and nothing gets skipped.
4
23
 
5
- ```bash
6
- npx dev-harness-cli init --stack python --target my-project
7
- cd my-project
8
- npx dev-harness-cli phase define
9
24
  ```
25
+ define → plan → build → verify → [simplify] → review → ship
26
+ ```
27
+
28
+ Each phase has **deterministic gates** (checks) that must pass before advancing. The agent does the work; harness validates the result.
10
29
 
11
30
  ## Install
12
31
 
13
32
  ```bash
14
33
  # Quick start (no install)
15
- npx dev-harness-cli --help
34
+ npx dev-harness-cli init --stack python --target my-project
16
35
 
17
36
  # Global install
18
37
  npm install -g dev-harness-cli
19
- harness-dev --help
20
-
21
- # Or clone and install
22
- git clone https://github.com/bakr-bagaber/dev-harness.git
23
- cd dev-harness && npm install -g .
38
+ dev-harness --help
24
39
  ```
25
40
 
26
- Requires **Node.js >= 18**.
41
+ Requires **Node.js >= 18**. Zero runtime dependencies.
27
42
 
28
43
  ## Quick Start
29
44
 
30
45
  ```bash
31
- # Scaffold a new project
32
- harness-dev init --stack python --target my-app
33
-
34
- # Check status
46
+ # 1. Scaffold a new project
47
+ dev-harness init --stack node --target my-app
35
48
  cd my-app
36
- harness-dev status
37
49
 
38
- # Start the DEFINE phase
39
- harness-dev phase define
50
+ # 2. Check status
51
+ dev-harness status
52
+
53
+ # 3. Run the DEFINE phase (agent writes specs)
54
+ dev-harness phase define
55
+
56
+ # 4. Validate (run gate checks)
57
+ dev-harness validate
58
+
59
+ # 5. Continue through pipeline
60
+ dev-harness phase plan
61
+ dev-harness phase build
62
+ dev-harness phase verify
63
+ dev-harness phase review
64
+ dev-harness phase ship
65
+ ```
66
+
67
+ ## Project Structure
68
+
69
+ When you run `dev-harness init`, all harness-managed files go into a `harness/` subfolder — keeping your project root clean:
70
+
71
+ ```
72
+ my-project/
73
+ ├── AGENTS.md # Agent instructions (root — tools expect it here)
74
+ ├── .gitignore # Git ignore rules
75
+ ├── package.json # Your project's package file
76
+ ├── src/ # Your source code
77
+ ├── tests/ # Your tests
78
+ └── harness/ # All harness-managed files
79
+ ├── config.json # Harness configuration + state
80
+ ├── progress.md # Session state + lessons learned
81
+ ├── sprint-contract.md # Pre-build agreement
82
+ ├── evaluator-rubric.md # Quality scorecard
83
+ ├── session-handoff.md # Context for session transitions
84
+ ├── clean-state-checklist.md
85
+ ├── features/
86
+ │ ├── feature-list.json # Feature tracking
87
+ │ └── feature-list.schema.json
88
+ ├── docs/
89
+ │ ├── ARCHITECTURE.md # Architecture decisions
90
+ │ ├── CONSTRAINTS.md # Technical constraints
91
+ │ ├── DECISIONS.md # Decision log
92
+ │ ├── api-patterns.md # API conventions
93
+ │ ├── agents/ # Agent role guides
94
+ │ │ ├── planner.md
95
+ │ │ ├── generator.md
96
+ │ │ ├── evaluator.md
97
+ │ │ └── simplifier.md
98
+ │ └── phases/ # Phase instructions
99
+ │ ├── define.md
100
+ │ ├── plan.md
101
+ │ ├── build.md
102
+ │ ├── verify.md
103
+ │ ├── simplify.md
104
+ │ ├── review.md
105
+ │ └── ship.md
106
+ ├── ci/
107
+ │ ├── github-actions.yml
108
+ │ └── gitlab-ci.yml
109
+ └── scripts/
110
+ ├── init.sh
111
+ └── init.ps1
40
112
  ```
41
113
 
42
114
  ## Supported Stacks
43
115
 
44
- | Stack | Detection | Config File |
45
- |-------|-----------|-------------|
46
- | Python | `pyproject.toml`, `setup.py`, `*.py` | `pyproject.toml` |
47
- | Java | `pom.xml`, `build.gradle`, `*.java` | `pom.xml` |
48
- | Kotlin | `build.gradle.kts`, `*.kt` | `build.gradle.kts` |
116
+ 31 built-in stacks + custom stack support:
117
+
118
+ | Stack | Detection Files | Config File |
119
+ |-------|----------------|-------------|
49
120
  | Node.js | `package.json`, `*.js`, `*.ts` | `package.json` |
50
- | Go | `go.mod`, `*.go` | `go.mod` |
121
+ | Python | `pyproject.toml`, `setup.py`, `*.py` | `pyproject.toml` |
51
122
  | Rust | `Cargo.toml`, `*.rs` | `Cargo.toml` |
52
- | C | `*.c` | `CMakeLists.txt` |
53
- | C++ | `*.cpp`, `*.hpp` | `CMakeLists.txt` |
123
+ | Go | `go.mod`, `*.go` | `go.mod` |
124
+ | Java | `pom.xml`, `build.gradle`, `*.java` | `pom.xml` |
125
+ | C/C++ | `*.c`, `*.cpp`, `*.hpp` | `CMakeLists.txt` |
54
126
  | .NET | `*.cs`, `*.fs` | `global.json` |
55
- | MATLAB | `*.m` | (none) |
56
- | VHDL | `*.vhdl`, `*.vhd` | (none) |
57
- | Verilog | `*.v`, `*.sv` | (none) |
58
- | Generic | fallback | (none) |
127
+ | Ruby | `Gemfile`, `*.rb` | `Gemfile` |
128
+ | PHP | `composer.json`, `*.php` | `composer.json` |
129
+ | Swift | `Package.swift`, `*.swift` | `Package.swift` |
130
+ | + 21 more | | |
131
+
132
+ **Custom stacks:** Pass any name to `--stack` and fill `stackMeta` in `harness/config.json` during DEFINE phase.
59
133
 
60
134
  ## Commands
61
135
 
62
136
  | Command | Description |
63
137
  |---------|-------------|
64
- | `init` | Scaffold project (21 files) |
65
- | `status` | Show current state |
66
- | `phase <name>` | Invoke a phase |
67
- | `validate` | Run gate checks |
68
- | `config get/set` | Read/write config |
69
- | `learn <msg>` | Save a lesson |
70
- | `set-mode` | copilot / autopilot |
71
- | `pause` / `resume` | Control autopilot |
138
+ | `init` | Scaffold a new project with harness structure |
139
+ | `status` | Show current phase, stack, features, gates |
140
+ | `phase <name>` | Invoke a pipeline phase |
141
+ | `validate` | Run gate checks for current phase |
142
+ | `config list` | List all 29 configurable parameters |
143
+ | `config get <key>` | Get a config value |
144
+ | `config set <key> <value>` | Set a config value |
145
+ | `set-mode <copilot\|autopilot>` | Switch execution mode |
146
+ | `pause` / `resume` | Pause/resume autopilot |
72
147
  | `contract propose/review/status/escalate` | Sprint contract negotiation |
73
- | `worktree create/list/prune/remove` | Git worktree management |
74
- | `checkpoint create <label>` | Git tag checkpoint |
75
- | `rollback list/to/branch` | Rollback to checkpoint |
148
+ | `learn <message>` | Save a lesson to progress.md |
149
+ | `checkpoint create <label>` | Create a manual checkpoint |
150
+ | `rollback list/to/branch` | Restore to checkpoint |
151
+ | `worktree create/list/remove` | Git worktree management |
152
+ | `detect-tool` | Detect available agent tools |
76
153
 
77
- ## Phase Pipeline
154
+ ## Agent Tool Integration
78
155
 
79
- ```
80
- INIT → DEFINE → PLAN → BUILD → VERIFY → [SIMPLIFY] → REVIEW → SHIP
81
- ```
156
+ Harness works with any coding agent. Use `--agent-tool` during init to generate tool-specific files:
82
157
 
83
- Two loop modes:
84
- - **Copilot** (default): one phase at a time, human decides when to advance
85
- - **Autopilot**: auto-advances through pipeline after each gate passes
86
-
87
- ## Output Contracts
158
+ ```bash
159
+ # Claude Code generates CLAUDE.md
160
+ dev-harness init --stack node --agent-tool claude-code --target my-app
88
161
 
89
- All commands produce machine-parseable JSON with `--json`:
162
+ # Cursor generates .cursorrules
163
+ dev-harness init --stack node --agent-tool cursor --target my-app
90
164
 
91
- ```json
92
- {"command":"status","status":"ok","message":"Phase: define, Stack: Node.js",
93
- "currentPhase":"define","mode":"copilot","recentLessons":[]}
165
+ # GitHub Copilot → generates .github/copilot-instructions.md
166
+ dev-harness init --stack node --agent-tool copilot --target my-app
94
167
  ```
95
168
 
96
- Errors go to stderr: `{"error":"CliError","message":"...","exitCode":N}`
97
-
98
- Exit codes: `0` success, `1` validation failure, `2` usage error, `3` internal error
169
+ **18 supported tools:** claude-code, cursor, windsurf, gemini, copilot, cline, roo, kilo-code, amazon-q, codex, opencode, continue, aider, antigravity, openclaw, pi, hermes, generic.
99
170
 
100
- ## Architecture
171
+ See [docs/TOOL_INTEGRATION.md](docs/TOOL_INTEGRATION.md) for per-tool setup guides.
101
172
 
102
- ```
103
- cli/
104
- ├── harness-dev.mjs — Entry point + command router
105
- ├── lib/
106
- │ ├── args.mjs — Argument parser
107
- │ ├── errors.mjs — Error handling + exit codes
108
- │ ├── help.mjs — Help text + per-command help
109
- │ ├── detect-stack.mjs — 13-stack detection engine
110
- │ ├── vars.mjs — Stack variable resolution
111
- │ ├── templates.mjs — Template engine ({{VAR}} substitution)
112
- │ ├── state.mjs — Config I/O + phase transitions
113
- │ ├── phases.mjs — Pure phase pipeline logic
114
- │ ├── progress.mjs — progress.md reader/writer
115
- │ ├── gates.mjs — Phase gate validation
116
- │ ├── ralph-inner.mjs — Inner loop engine
117
- │ ├── ralph-outer.mjs — Outer loop engine
118
- │ ├── ralph-output.mjs — Phase instruction text builders
119
- │ ├── modes.mjs — Copilot/autopilot modes
120
- │ ├── contract.mjs — Sprint contract negotiation
121
- │ ├── git.mjs — Centralized git operations
122
- │ ├── paths.mjs — Centralized path resolution
123
- │ ├── file-io.mjs — JSON/text I/O helpers
124
- │ ├── output.mjs — JSON/human output helpers
125
- │ ├── command-helpers.mjs— Shared arg parsing + phaseLabel
126
- │ ├── constants.mjs — Centralized magic numbers
127
- │ ├── scaffold.mjs — Stack-specific scaffolding assets
128
- │ ├── validate-schema.mjs— Minimal JSON-schema validator
129
- │ └── schemas/
130
- │ └── stacks.json — 13-stack metadata (CLI-internal)
131
- ├── commands/ — 13 command handlers
132
- │ ├── init.mjs, status.mjs, phase.mjs, validate.mjs, config.mjs
133
- │ ├── learn.mjs, set-mode.mjs, pause.mjs, resume.mjs
134
- │ └── contract.mjs, worktree.mjs, rollback.mjs, checkpoint.mjs
135
- templates/ — Scaffold templates (AGENTS.md, init.sh, ci/, docs/, etc.)
136
- schema/ — Published JSON schemas (harness-config, feature-list)
137
- test/ — Test suites (test-t*.mjs + run-all.mjs)
138
- dist/install.sh — One-liner installation script (curl-pipe-bash)
139
- adapters/ — Tool adapters (claude-code, cursor, codex, hermes, generic)
140
- docs/ — TOOL_INTEGRATION.md (per-tool setup guides)
141
- references/ — Historical audit reports
142
- history/ — Project audit log, changelog, decisions, issues
143
- docs-site-templates/ — Docusaurus/Sphinx scaffolds (experimental)
144
- ```
173
+ ## Gates
145
174
 
146
- ## Agent Integration
147
-
148
- harness-dev works with any coding agent via stdout JSON contracts and AGENTS.md project conventions. Use `--agent-tool` at scaffold time to generate tool-specific files, or `detect-tool` to discover which tools are configured.
175
+ Gates are deterministic checks that must pass before advancing to the next phase. Enable with:
149
176
 
150
177
  ```bash
151
- # Scaffold with a specific tool
152
- harness-dev init --stack node --agent-tool claude-code --target my-project
153
-
154
- # Or scaffold generically (AGENTS.md only — works with most tools)
155
- harness-dev init --stack node --target my-project
156
-
157
- # Detect which tools are configured
158
- harness-dev detect-tool --target my-project
178
+ dev-harness config set gates.enabled true
159
179
  ```
160
180
 
161
- **Supported tools:** `claude-code` (CLAUDE.md), `cursor` (.cursorrules), `codex`, `aider`, `continue`, `opencode` (all read AGENTS.md), `hermes` (SKILL.md), `generic` (default).
181
+ | Phase | Gates |
182
+ |-------|-------|
183
+ | DEFINE | feature-branch, contract-agreed |
184
+ | PLAN | git-clean |
185
+ | BUILD | (coverage if enabled) |
186
+ | VERIFY | (coverage if enabled) |
187
+ | SIMPLIFY | git-clean, no-empty-dirs |
188
+ | REVIEW | branch-up-to-date, rubric-exists, readme-exists, architecture-doc, decisions-logged |
189
+ | SHIP | git-clean, tagged, changelog, readme-exists, license-exists, changelog-content, contributing-exists, no-empty-dirs |
162
190
 
163
- See [docs/TOOL_INTEGRATION.md](docs/TOOL_INTEGRATION.md) for per-tool setup guides and the adapter architecture.
191
+ ## Configuration
164
192
 
165
- ### Claude Code
193
+ All configuration lives in `harness/config.json`. View with:
166
194
 
167
195
  ```bash
168
- harness-dev init --stack node --agent-tool claude-code --target my-project
169
- cd my-project
170
- # Claude reads CLAUDE.md automatically
171
- harness-dev phase build
172
- # Claude follows the phase instructions, runs:
173
- harness-dev validate
196
+ dev-harness config list
174
197
  ```
175
198
 
176
- ### Codex CLI
199
+ 29 parameters across 8 groups: Execution, Stack, Agent Tool, Gates, Git, Phases, Agent Tones, Runtime State.
177
200
 
178
- ```bash
179
- harness-dev init --stack go --agent-tool codex --target my-project
180
- cd my-project
181
- # Codex reads AGENTS.md from project root
182
- harness-dev status --json
183
- # → Machine-readable state for agent decision-making
184
- ```
185
-
186
- ### Cursor
201
+ See [docs/CONFIGURATION.md](docs/CONFIGURATION.md) for full reference.
187
202
 
188
- ```bash
189
- harness-dev init --stack rust --agent-tool cursor --target my-project
190
- cd my-project
191
- # .cursorrules generated with harness conventions
192
- harness-dev phase build
193
- ```
203
+ ## JSON Output
194
204
 
195
- ### Generic Agent Workflow
205
+ All commands support `--json` for machine-parseable output:
196
206
 
197
207
  ```bash
198
- harness-dev phase build
199
- # Prints task instructions for agent
200
- # Agent reads AGENTS.md + progress.md + sprint-contract.md
201
- # → Agent implements → calls `harness-dev validate`
202
- # → Gate passes → `harness-dev phase verify`
208
+ dev-harness status --json
209
+ dev-harness phase define --json
210
+ dev-harness validate --json
203
211
  ```
204
212
 
205
- ## API Reference
206
-
207
- ### JSON Output Contract (all commands)
208
-
209
213
  ```json
210
214
  {
211
- "command": "<command_name>",
212
- "status": "ok" | "not_implemented" | "error",
213
- "message": "Human-readable status or error detail"
215
+ "command": "status",
216
+ "status": "ok",
217
+ "currentPhase": "define",
218
+ "stack": "node",
219
+ "mode": "copilot"
214
220
  }
215
221
  ```
216
222
 
217
- Additional command-specific fields are included (e.g. `currentPhase`, `stack`, `mode`).
218
-
219
- ### Error Contract
220
-
221
- ```json
222
- {
223
- "error": "CliError",
224
- "message": "Description of the problem",
225
- "exitCode": 1
226
- }
227
- ```
228
-
229
- Errors always go to **stderr** so stdout stays parseable.
230
-
231
- ### Exit Codes
232
-
233
- | Code | Meaning |
234
- |------|---------|
235
- | 0 | Success |
236
- | 1 | Validation failure |
237
- | 2 | Usage error |
238
- | 3 | Internal error |
239
-
240
- ### All Commands
241
-
242
- | Command | JSON Fields | Description |
243
- |---------|-------------|-------------|
244
- | `init` | `project`, `stack`, `filesCreated` | Scaffold harness project |
245
- | `status` | `currentPhase`, `mode`, `stack`, `gateStatus`, `checksPassing`, `checksTotal`, `recentLessons`, `nextAction` | Show current state |
246
- | `phase <name>` | `phase`, `previousPhase`, `gateResult`, `iteration` | Invoke a phase |
247
- | `validate` | `phase`, `checks[]`, `overall`, `failures[]` | Run gate checks |
248
- | `config get <key>` | `key`, `value` | Read config value |
249
- | `config set <key> <value>` | `key`, `previous`, `current` | Write config value |
250
- | `learn <msg>` | `lesson` | Append a lesson |
251
- | `set-mode copilot\|autopilot` | `previous`, `current` | Switch mode |
252
- | `pause` / `resume` | `paused` | Control autopilot |
253
- | `contract propose\|review\|status\|escalate` | `status`, `agreed`, `round`, `pinned` | Sprint contract |
254
- | `worktree create\|list\|prune\|remove` | `worktrees[]`, `action`, `name` | Git worktree |
255
- | `checkpoint create <label>` | `tag`, `commit` | Git checkpoint |
256
- | `rollback list\|to\|branch` | `checkpoints[]`, `restored` | Rollback |
257
-
258
- ## Project Structure
259
-
260
- ```
261
- cli/ — CLI source
262
- ├── harness-dev.mjs — Entry point + command router
263
- ├── lib/ — Core libraries
264
- │ ├── git.mjs — Centralized git operations
265
- │ ├── state.mjs — Config I/O + phase transitions (re-exports phases.mjs)
266
- │ ├── phases.mjs — Pure phase pipeline logic
267
- │ ├── ralph-inner.mjs — Inner loop (work → validate → retry)
268
- │ ├── ralph-outer.mjs — Outer loop (phase auto-advance)
269
- │ ├── ralph-output.mjs — Phase instruction text builders
270
- │ ├── gates.mjs — Phase gate validation
271
- │ ├── contract.mjs — Sprint contract negotiation
272
- │ ├── paths.mjs — Centralized path resolution
273
- │ ├── file-io.mjs — JSON/text I/O helpers
274
- │ ├── output.mjs — JSON/human output helpers
275
- │ ├── command-helpers.mjs — Shared arg parsing + phaseLabel
276
- │ ├── constants.mjs — Centralized magic numbers
277
- │ ├── scaffold.mjs — Stack-specific scaffolding assets
278
- │ ├── templates.mjs — Template engine
279
- │ ├── detect-stack.mjs — Stack detection
280
- │ ├── validate-schema.mjs — Minimal JSON-schema validator
281
- │ └── schemas/stacks.json — Stack metadata (CLI-internal)
282
- ├── commands/ — Command handlers (13 commands)
283
- templates/ — Scaffold templates (AGENTS.md, init.sh, ci/, docs/, etc.)
284
- schema/ — Published JSON schemas (harness-config, feature-list)
285
- test/ — Test suites (test-t*.mjs + run-all.mjs)
286
- dist/install.sh — One-liner install script
287
- adapters/ — Tool adapters (claude-code, cursor, codex, hermes, generic)
288
- docs/ — TOOL_INTEGRATION.md (per-tool setup guides)
289
- references/ — Historical audit reports (T5-T14)
290
- history/ — Project audit log, changelog, decisions, issues
291
- docs-site-templates/ — Docusaurus/Sphinx scaffolds (experimental, T25)
292
- PROJECT_PLAN.md — Full task breakdown (T1-T20)
293
- SPEC.md — Original architecture specification
294
- dev-harness.md — Internal project note (Obsidian)
295
- ```
223
+ Errors go to stderr. Exit codes: `0` success, `1` validation, `2` usage, `3` internal.
296
224
 
297
225
  ## License
298
226
 
@@ -9,7 +9,7 @@
9
9
  * save named recovery points (e.g. "before-refactor") that appear
10
10
  * in `rollback list` and can be used with `rollback to/branch`.
11
11
  *
12
- * Usage: harness-dev checkpoint create <label>
12
+ * Usage: dev-harness checkpoint create <label>
13
13
  */
14
14
  import { die, CliError, EXIT } from '../lib/errors.mjs';
15
15
  import { execGit, getGitRoot, gitTagExists, createGitTag } from '../lib/git.mjs';
@@ -21,7 +21,7 @@ export default async function checkpointCommand(args) {
21
21
  const label = args.positionals[0];
22
22
 
23
23
  if (sub !== 'create' || !label) {
24
- die(new CliError('Usage: harness-dev checkpoint create <label> [--force]', EXIT.USAGE_ERROR), json);
24
+ die(new CliError('Usage: dev-harness checkpoint create <label> [--force]', EXIT.USAGE_ERROR), json);
25
25
  return;
26
26
  }
27
27
 
@@ -4,16 +4,16 @@
4
4
  * Uses state.mjs for dot-notation read/write with persistence.
5
5
  *
6
6
  * Usage:
7
- * harness-dev config list — list all parameters with descriptions
8
- * harness-dev config get [key] — get a value or all config
9
- * harness-dev config set <key> <value> — set a value
7
+ * dev-harness config list — list all parameters with descriptions
8
+ * dev-harness config get [key] — get a value or all config
9
+ * dev-harness config set <key> <value> — set a value
10
10
  *
11
11
  * Examples:
12
- * harness-dev config list
13
- * harness-dev config list --json
14
- * harness-dev config get gates.enabled
15
- * harness-dev config set gates.enabled true
16
- * harness-dev config set maxRetries 5
12
+ * dev-harness config list
13
+ * dev-harness config list --json
14
+ * dev-harness config get gates.enabled
15
+ * dev-harness config set gates.enabled true
16
+ * dev-harness config set maxRetries 5
17
17
  */
18
18
  import { resolve } from 'node:path';
19
19
  import { die, CliError, EXIT } from '../lib/errors.mjs';
@@ -29,7 +29,7 @@ export default async function configCommand(args) {
29
29
 
30
30
  if (!sub || (sub !== 'get' && sub !== 'set' && sub !== 'list')) {
31
31
  die(new CliError(
32
- 'Usage: harness-dev config list | config get [key] | config set <key> <value>',
32
+ 'Usage: dev-harness config list | config get [key] | config set <key> <value>',
33
33
  EXIT.USAGE_ERROR,
34
34
  ), json);
35
35
  return;
@@ -75,7 +75,7 @@ export default async function configCommand(args) {
75
75
  // Human output — grouped table
76
76
  process.stdout.write('═══ Harness Configuration ═══\n\n');
77
77
  if (!ok) {
78
- process.stdout.write(' No harness-config.json found. Run: harness-dev init\n\n');
78
+ process.stdout.write(' No harness/config.json found. Run: dev-harness init\n\n');
79
79
  return;
80
80
  }
81
81
 
@@ -102,7 +102,7 @@ export default async function configCommand(args) {
102
102
  process.stdout.write('\n');
103
103
  }
104
104
 
105
- process.stdout.write('Edit with: harness-dev config set <key> <value>\n');
105
+ process.stdout.write('Edit with: dev-harness config set <key> <value>\n');
106
106
  process.stdout.write('Full docs: docs/CONFIGURATION.md\n');
107
107
  return;
108
108
  }
@@ -141,7 +141,7 @@ export default async function configCommand(args) {
141
141
  if (sub === 'set') {
142
142
  if (pos.length < 2) {
143
143
  die(new CliError(
144
- 'Usage: harness-dev config set <key> <value>\n' +
144
+ 'Usage: dev-harness config set <key> <value>\n' +
145
145
  ' String values: config set mode copilot\n' +
146
146
  ' Boolean values: config set gates.enabled true\n' +
147
147
  ' Numeric values: config set maxRetries 5',
@@ -4,10 +4,10 @@
4
4
  * Manages the generator-evaluator agreement loop.
5
5
  *
6
6
  * Usage:
7
- * harness-dev contract propose [--scope "msg"] [--exclusions "msg"]
8
- * harness-dev contract review [--agreed|--needs-revision]
9
- * harness-dev contract status
10
- * harness-dev contract escalate [--reason "msg"]
7
+ * dev-harness contract propose [--scope "msg"] [--exclusions "msg"]
8
+ * dev-harness contract review [--agreed|--needs-revision]
9
+ * dev-harness contract status
10
+ * dev-harness contract escalate [--reason "msg"]
11
11
  */
12
12
  import { resolve } from 'node:path';
13
13
  import { die, CliError, EXIT } from '../lib/errors.mjs';
@@ -22,7 +22,7 @@ export default async function contractCommand(args) {
22
22
  const sub = args.subcommand;
23
23
 
24
24
  if (!sub || !SUBCOMMANDS.includes(sub)) {
25
- die(new CliError(`Usage: harness-dev contract ${SUBCOMMANDS.join('|')}`, EXIT.USAGE_ERROR), json);
25
+ die(new CliError(`Usage: dev-harness contract ${SUBCOMMANDS.join('|')}`, EXIT.USAGE_ERROR), json);
26
26
  return;
27
27
  }
28
28
 
@@ -34,7 +34,7 @@ export default async function contractCommand(args) {
34
34
 
35
35
  if (!scope) {
36
36
  die(new CliError(
37
- 'Usage: harness-dev contract propose --scope "I will build X" [--exclusions "W"] [--criteria "test1|test2"]',
37
+ 'Usage: dev-harness contract propose --scope "I will build X" [--exclusions "W"] [--criteria "test1|test2"]',
38
38
  EXIT.USAGE_ERROR,
39
39
  ), json);
40
40
  return;
@@ -53,7 +53,7 @@ export default async function contractCommand(args) {
53
53
  }
54
54
 
55
55
  if (result.ok) {
56
- process.stdout.write('✓ Contract proposed. Run: harness-dev contract review\n');
56
+ process.stdout.write('✓ Contract proposed. Run: dev-harness contract review\n');
57
57
  } else {
58
58
  process.stderr.write(`✗ ${result.error}\n`);
59
59
  }
@@ -68,7 +68,7 @@ export default async function contractCommand(args) {
68
68
 
69
69
  if (!agreed && !needsRevision) {
70
70
  die(new CliError(
71
- 'Usage: harness-dev contract review --agreed [--notes "msg"] OR --needs-revision [--notes "msg"]',
71
+ 'Usage: dev-harness contract review --agreed [--notes "msg"] OR --needs-revision [--notes "msg"]',
72
72
  EXIT.USAGE_ERROR,
73
73
  ), json);
74
74
  return;
@@ -116,7 +116,7 @@ export default async function contractCommand(args) {
116
116
  rounds,
117
117
  message: status
118
118
  ? `Contract ${status} (round ${rounds}/5)`
119
- : 'No sprint-contract.md found. Run: harness-dev contract propose',
119
+ : 'No sprint-contract.md found. Run: dev-harness contract propose',
120
120
  }) + '\n');
121
121
  return;
122
122
  }
@@ -124,7 +124,7 @@ export default async function contractCommand(args) {
124
124
  if (status) {
125
125
  process.stdout.write(`Contract status: ${status} (round ${rounds}/5)\n`);
126
126
  } else {
127
- process.stdout.write('No sprint-contract.md found. Run: harness-dev contract propose\n');
127
+ process.stdout.write('No sprint-contract.md found. Run: dev-harness contract propose\n');
128
128
  }
129
129
  return;
130
130
  }
@@ -12,7 +12,7 @@
12
12
  * Also reads harness-config.json agentTool field if present.
13
13
  *
14
14
  * Usage:
15
- * harness-dev detect-tool [--target <dir>] [--json]
15
+ * dev-harness detect-tool [--target <dir>] [--json]
16
16
  */
17
17
  import { existsSync } from 'node:fs';
18
18
  import { resolve } from 'node:path';
@@ -20,12 +20,13 @@ import { parseCommandArgs } from '../lib/command-helpers.mjs';
20
20
  import { emitJson, emitHuman } from '../lib/output.mjs';
21
21
  import { loadConfig } from '../lib/state.mjs';
22
22
  import { getAllDetectionSignatures, AGENTS_MD_TOOLS, TOOL_REGISTRY } from '../lib/tool-registry.mjs';
23
+ import { AGENTS_PATH } from '../lib/paths.mjs';
23
24
 
24
25
  export default async function detectToolCommand(args) {
25
26
  const { json, targetDir } = parseCommandArgs(args);
26
27
 
27
28
  const detected = [];
28
- const hasAgentsMd = existsSync(resolve(targetDir, 'AGENTS.md'));
29
+ const hasAgentsMd = existsSync(AGENTS_PATH(targetDir));
29
30
 
30
31
  // 1. Scan for tool-specific detection files (from registry)
31
32
  for (const { tool, file } of getAllDetectionSignatures()) {
@@ -79,7 +80,7 @@ export default async function detectToolCommand(args) {
79
80
  status: 'ok',
80
81
  message: detected.length > 0
81
82
  ? `Detected ${detected.length} agent tool(s): ${detected.join(', ')}`
82
- : 'No agent tools detected. Run: harness-dev init',
83
+ : 'No agent tools detected. Run: dev-harness init',
83
84
  available: detected,
84
85
  configured: configuredTool,
85
86
  recommended,
@@ -103,7 +104,7 @@ export default async function detectToolCommand(args) {
103
104
  }
104
105
  } else {
105
106
  emitHuman(` No agent tools detected.\n`);
106
- emitHuman(` Run: harness-dev init to scaffold a project.\n`);
107
+ emitHuman(` Run: dev-harness init to scaffold a project.\n`);
107
108
  }
108
109
  if (hasAgentsMd) {
109
110
  emitHuman(`\n AGENTS.md present — tools that read it natively are available.\n`);