@harness-engineering/cli 3.1.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/personas/harness-pm.yaml +33 -0
- package/dist/agents/skills/claude-code/acceptance-eval/SKILL.md +92 -0
- package/dist/agents/skills/claude-code/acceptance-eval/skill.yaml +54 -0
- package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +46 -38
- package/dist/agents/skills/claude-code/harness-brainstorming/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +10 -11
- package/dist/agents/skills/claude-code/harness-execution/SKILL.md +24 -26
- package/dist/agents/skills/claude-code/harness-integration/SKILL.md +21 -19
- package/dist/agents/skills/claude-code/harness-maintenance-pipeline/SKILL.md +173 -0
- package/dist/agents/skills/claude-code/harness-maintenance-pipeline/skill.yaml +43 -0
- package/dist/agents/skills/claude-code/harness-onboarding/SKILL.md +2 -0
- package/dist/agents/skills/claude-code/harness-planning/SKILL.md +17 -40
- package/dist/agents/skills/claude-code/harness-pulse/SKILL.md +1 -1
- package/dist/agents/skills/claude-code/harness-roadmap/SKILL.md +17 -0
- package/dist/agents/skills/claude-code/harness-roadmap-pilot/SKILL.md +8 -0
- package/dist/agents/skills/claude-code/harness-verification/SKILL.md +9 -12
- package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +112 -126
- package/dist/agents/skills/claude-code/outcome-eval/SKILL.md +1 -0
- package/dist/agents/skills/codex/acceptance-eval/SKILL.md +92 -0
- package/dist/agents/skills/codex/acceptance-eval/skill.yaml +54 -0
- package/dist/agents/skills/codex/harness-brainstorming/SKILL.md +46 -38
- package/dist/agents/skills/codex/harness-brainstorming/skill.yaml +1 -0
- package/dist/agents/skills/codex/harness-code-review/SKILL.md +10 -11
- package/dist/agents/skills/codex/harness-execution/SKILL.md +24 -26
- package/dist/agents/skills/codex/harness-integration/SKILL.md +21 -19
- package/dist/agents/skills/codex/harness-maintenance-pipeline/SKILL.md +173 -0
- package/dist/agents/skills/codex/harness-maintenance-pipeline/skill.yaml +43 -0
- package/dist/agents/skills/codex/harness-onboarding/SKILL.md +2 -0
- package/dist/agents/skills/codex/harness-planning/SKILL.md +17 -40
- package/dist/agents/skills/codex/harness-pulse/SKILL.md +1 -1
- package/dist/agents/skills/codex/harness-roadmap/SKILL.md +17 -0
- package/dist/agents/skills/codex/harness-roadmap-pilot/SKILL.md +8 -0
- package/dist/agents/skills/codex/harness-verification/SKILL.md +9 -12
- package/dist/agents/skills/codex/initialize-harness-project/SKILL.md +112 -126
- package/dist/agents/skills/codex/outcome-eval/SKILL.md +1 -0
- package/dist/agents/skills/cursor/acceptance-eval/SKILL.md +92 -0
- package/dist/agents/skills/cursor/acceptance-eval/skill.yaml +54 -0
- package/dist/agents/skills/cursor/harness-brainstorming/SKILL.md +46 -38
- package/dist/agents/skills/cursor/harness-brainstorming/skill.yaml +1 -0
- package/dist/agents/skills/cursor/harness-code-review/SKILL.md +10 -11
- package/dist/agents/skills/cursor/harness-execution/SKILL.md +24 -26
- package/dist/agents/skills/cursor/harness-integration/SKILL.md +21 -19
- package/dist/agents/skills/cursor/harness-maintenance-pipeline/SKILL.md +173 -0
- package/dist/agents/skills/cursor/harness-maintenance-pipeline/skill.yaml +43 -0
- package/dist/agents/skills/cursor/harness-onboarding/SKILL.md +2 -0
- package/dist/agents/skills/cursor/harness-planning/SKILL.md +17 -40
- package/dist/agents/skills/cursor/harness-pulse/SKILL.md +1 -1
- package/dist/agents/skills/cursor/harness-roadmap/SKILL.md +17 -0
- package/dist/agents/skills/cursor/harness-roadmap-pilot/SKILL.md +8 -0
- package/dist/agents/skills/cursor/harness-verification/SKILL.md +9 -12
- package/dist/agents/skills/cursor/initialize-harness-project/SKILL.md +112 -126
- package/dist/agents/skills/cursor/outcome-eval/SKILL.md +1 -0
- package/dist/agents/skills/gemini-cli/acceptance-eval/SKILL.md +92 -0
- package/dist/agents/skills/gemini-cli/acceptance-eval/skill.yaml +54 -0
- package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +46 -38
- package/dist/agents/skills/gemini-cli/harness-brainstorming/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-code-review/SKILL.md +10 -11
- package/dist/agents/skills/gemini-cli/harness-execution/SKILL.md +24 -26
- package/dist/agents/skills/gemini-cli/harness-integration/SKILL.md +21 -19
- package/dist/agents/skills/gemini-cli/harness-maintenance-pipeline/SKILL.md +173 -0
- package/dist/agents/skills/gemini-cli/harness-maintenance-pipeline/skill.yaml +43 -0
- package/dist/agents/skills/gemini-cli/harness-onboarding/SKILL.md +2 -0
- package/dist/agents/skills/gemini-cli/harness-planning/SKILL.md +17 -40
- package/dist/agents/skills/gemini-cli/harness-pulse/SKILL.md +1 -1
- package/dist/agents/skills/gemini-cli/harness-roadmap/SKILL.md +17 -0
- package/dist/agents/skills/gemini-cli/harness-roadmap-pilot/SKILL.md +8 -0
- package/dist/agents/skills/gemini-cli/harness-verification/SKILL.md +9 -12
- package/dist/agents/skills/gemini-cli/initialize-harness-project/SKILL.md +112 -126
- package/dist/agents/skills/gemini-cli/outcome-eval/SKILL.md +1 -0
- package/dist/agents/skills/tests/interaction-channel.test.ts +64 -0
- package/dist/{agents-md-YYCLGMBF.js → agents-md-7OSNWU52.js} +2 -2
- package/dist/{architecture-5KPP4ID4.js → architecture-2XYGJGT3.js} +3 -3
- package/dist/{assess-project-B6ENHUAU.js → assess-project-3KPP2D6M.js} +1 -1
- package/dist/bin/harness-mcp.js +16 -15
- package/dist/bin/harness.js +27 -25
- package/dist/{check-phase-gate-REG3HWYC.js → check-phase-gate-46U5AAXE.js} +4 -3
- package/dist/{chunk-HIPBU2Q4.js → chunk-363V6GPR.js} +5 -5
- package/dist/{chunk-DNX35Q5K.js → chunk-6NCREWWM.js} +2 -2
- package/dist/{chunk-FL5SLUKZ.js → chunk-6YXCZV33.js} +2141 -929
- package/dist/{chunk-UBTMPO5H.js → chunk-AK67S3O4.js} +3 -3
- package/dist/{chunk-ERZCC5VH.js → chunk-BV45354Q.js} +3 -3
- package/dist/{chunk-ZOUJP3EY.js → chunk-ERILXQBP.js} +1153 -484
- package/dist/{chunk-BXKNWSG4.js → chunk-FZ4Q73HA.js} +1 -1
- package/dist/{chunk-PZX2Y3RV.js → chunk-GXCPDAS5.js} +3 -3
- package/dist/{chunk-C2ZGWMTN.js → chunk-HMW3C5DP.js} +2 -2
- package/dist/{chunk-TE5YHHHZ.js → chunk-HXMAIVV2.js} +1 -1
- package/dist/{chunk-TCVQVHEF.js → chunk-IYWT3JJW.js} +1 -1
- package/dist/{chunk-A65QO5KN.js → chunk-KLPX55TI.js} +2953 -1162
- package/dist/{chunk-OQFEFVIN.js → chunk-MSBJ445U.js} +4 -4
- package/dist/{chunk-FUH4J43G.js → chunk-MYVTYFQD.js} +2 -2
- package/dist/{chunk-LMZ2JTNP.js → chunk-PHX45JYN.js} +5 -9
- package/dist/{chunk-ZRKFDE6M.js → chunk-S2RQPPL6.js} +1 -1
- package/dist/chunk-SPE7P4GL.js +61 -0
- package/dist/{chunk-YF3AY6KS.js → chunk-TTWNGOBT.js} +6 -6
- package/dist/{chunk-6B6UN6SG.js → chunk-UTJJJDNN.js} +11 -1
- package/dist/{chunk-WWACIIBA.js → chunk-V3ZQUCRH.js} +1 -1
- package/dist/{chunk-XEOSSKIB.js → chunk-VTU3QOJT.js} +48 -4
- package/dist/{chunk-IF3JK3G5.js → chunk-VTUINXWR.js} +1 -1
- package/dist/{chunk-27AJKSQY.js → chunk-WBVCN35T.js} +1 -1
- package/dist/{chunk-RGQXHCCH.js → chunk-WL3O2PKJ.js} +6 -6
- package/dist/{chunk-YQAFKOOL.js → chunk-XFHZ7GCI.js} +1 -1
- package/dist/chunk-Y6SUQC32.js +9 -0
- package/dist/{chunk-XZ2Q4UTW.js → chunk-ZEYAOYJL.js} +1 -1
- package/dist/{ci-workflow-JEYYCBOC.js → ci-workflow-XJN4UO3Q.js} +2 -2
- package/dist/{dist-3HW4LCHE.js → dist-IPVFYGY2.js} +71 -15
- package/dist/{docs-YRMW7UED.js → docs-RSFZTNPG.js} +3 -3
- package/dist/{engine-E7H5U3AC.js → engine-DJIHY4JT.js} +2 -2
- package/dist/{entropy-3JBKCGJJ.js → entropy-EAEKJKRM.js} +2 -2
- package/dist/{feedback-U6VJ6AUJ.js → feedback-JT5X3DBC.js} +1 -1
- package/dist/{generate-agent-definitions-S2FRZF4Y.js → generate-agent-definitions-CC6KED3E.js} +4 -4
- package/dist/hooks/adoption-tracker.js +6 -5
- package/dist/hooks/protect-config.js +15 -5
- package/dist/{index-builder-3AOQ3ZII.js → index-builder-52IJJHJC.js} +2 -2
- package/dist/index.d.ts +8 -8
- package/dist/index.js +27 -25
- package/dist/{loader-RGQJYERV.js → loader-UWNVTYBY.js} +2 -2
- package/dist/{mcp-NDTFZXWF.js → mcp-TCLNK7HG.js} +18 -17
- package/dist/{performance-FPWKC4CN.js → performance-R6O3N3UB.js} +3 -3
- package/dist/{review-pipeline-WUHG7PHO.js → review-pipeline-MOOWXWSQ.js} +2 -2
- package/dist/{runtime-Q3ORD7LW.js → runtime-RIWQUKBQ.js} +2 -2
- package/dist/{security-JDHTRBGC.js → security-U76C54W6.js} +1 -1
- package/dist/{skill-executor-MOCUIAYS.js → skill-executor-BGUCAVBU.js} +2 -2
- package/dist/state-events-F44CUUZG.js +25 -0
- package/dist/{validate-G3LKBOYA.js → validate-IUAV7MOU.js} +3 -3
- package/dist/{validate-cross-check-4ITA72DF.js → validate-cross-check-M2ZM6RFY.js} +2 -2
- package/package.json +7 -7
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
- When the problem space is ambiguous and needs exploration
|
|
9
9
|
- When multiple approaches exist and tradeoffs must be weighed
|
|
10
10
|
- When `on_new_feature` trigger fires and scope is non-trivial
|
|
11
|
-
- NOT when the implementation path is already clear (go straight to harness-planning)
|
|
11
|
+
- NOT when the implementation path is already clear (go straight to harness-planning, or harness-autopilot if the spec already exists)
|
|
12
12
|
- NOT when fixing a bug with an obvious root cause (use harness-debugging or harness-tdd)
|
|
13
13
|
- NOT for simple refactors with no design decisions (use harness-refactoring)
|
|
14
14
|
|
|
@@ -64,22 +64,23 @@ When no arguments are provided (standalone invocation), the skill operates exact
|
|
|
64
64
|
|
|
65
65
|
### Phase 2: EVALUATE -- Ask Questions and Narrow
|
|
66
66
|
|
|
67
|
-
1. **Ask ONE question at a time.** Ask the most important question first. Wait for the answer. Let it inform the next question.
|
|
67
|
+
1. **Ask ONE question at a time, in plain text.** Ask the most important question first. Wait for the answer. Let it inform the next question.
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
69
|
+
**Ask directly in your reply. Do NOT route the question through `emit_interaction`, `AskUserQuestion`, or any tool.** `emit_interaction` records the question in state but does not display it to the human — the client collapses it to "Called harness" and the rendered prompt only returns to the model, so the human sees nothing and you end up narrating a question they cannot answer. `AskUserQuestion` is Claude-Code-only and caps headers at 12 chars / 4 options. Plain text in your own message is the only channel that reliably reaches the human across every tool (Claude Code, Cursor, Codex, Gemini CLI).
|
|
70
|
+
|
|
71
|
+
Present the question as a markdown table so tradeoffs are scannable, state your recommendation, then STOP and wait for the human's reply:
|
|
72
|
+
|
|
73
|
+
```markdown
|
|
74
|
+
### Decision needed: For auth, which approach should we use?
|
|
75
|
+
|
|
76
|
+
| | A) Existing JWT middleware | B) OAuth2 via provider X | C) External auth service |
|
|
77
|
+
| ---------- | -------------------------- | ------------------------ | ------------------------ |
|
|
78
|
+
| **Pros** | Already in codebase | Industry standard | Zero maintenance |
|
|
79
|
+
| **Cons** | No refresh tokens | New dependency | Vendor lock-in; cost |
|
|
80
|
+
| **Risk** | Low | Medium | Medium |
|
|
81
|
+
| **Effort** | Low | Medium | Low |
|
|
82
|
+
|
|
83
|
+
**Recommendation:** A) Existing JWT middleware (confidence: high) — sufficient for current requirements.
|
|
83
84
|
```
|
|
84
85
|
|
|
85
86
|
2. **Prefer multiple choice over open-ended questions.** Give 2-4 concrete options with brief tradeoff notes.
|
|
@@ -169,24 +170,21 @@ These flow into `handoff.json` `contextKeywords` field. Select keywords that hel
|
|
|
169
170
|
|
|
170
171
|
5. **Run `harness validate`** to verify proper placement and project health.
|
|
171
172
|
|
|
172
|
-
6. **Request sign-off
|
|
173
|
+
6. **Request sign-off in plain text.** Ask directly in your reply — do NOT route the request through `emit_interaction` or `AskUserQuestion` (the human will not see it). Present it as:
|
|
173
174
|
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
risk: "low"
|
|
183
|
-
}
|
|
184
|
-
})
|
|
175
|
+
```markdown
|
|
176
|
+
Approve spec at <file-path>?
|
|
177
|
+
|
|
178
|
+
Context: <one-paragraph summary>
|
|
179
|
+
Impact: Spec approval unlocks implementation planning. No code changes yet.
|
|
180
|
+
Risk: low
|
|
181
|
+
|
|
182
|
+
Proceed? (yes/no)
|
|
185
183
|
```
|
|
186
184
|
|
|
187
|
-
The human must explicitly approve before this skill is complete.
|
|
185
|
+
The human must explicitly approve (a clear "yes") before this skill is complete.
|
|
188
186
|
|
|
189
|
-
7. **Promote the roadmap row.** If `docs/roadmap.md`
|
|
187
|
+
7. **Promote the roadmap row.** If a roadmap exists (a `docs/roadmap.md` aggregate **or** a `docs/roadmap.d/` shard directory), transition the named row to `planned` and link the spec in a single structured call (steps 7 and 8 are intentionally ordered so the commit captures the roadmap mutation). Skip silently only when no roadmap exists. In sharded mode `manage_roadmap promote` writes the single row's shard under `docs/roadmap.d/` **and** regenerates the `docs/roadmap.md` aggregate — both are staged in step 8.
|
|
190
188
|
- Derive the lookup key from the slash-command `ARGUMENTS` string (D1). Derive the summary from the spec title (the H1 heading).
|
|
191
189
|
- Call `manage_roadmap` with action `promote`, `feature: "<ARGUMENTS>"`, `spec: "docs/changes/<feature>/proposal.md"`, and `summary: "<H1>"`.
|
|
192
190
|
- Branch on the returned `PromoteResult` envelope:
|
|
@@ -210,11 +208,11 @@ These flow into `handoff.json` `contextKeywords` field. Select keywords that hel
|
|
|
210
208
|
8. **Commit spec artifacts and roadmap promotion.** After a successful promote (or a silent skip when no roadmap exists), commit the spec, skill recommendations, and the roadmap mutation together so the promotion ships atomically with the spec:
|
|
211
209
|
|
|
212
210
|
```bash
|
|
213
|
-
git add docs/changes/<feature>/proposal.md docs/changes/<feature>/SKILLS.md docs/roadmap.md
|
|
211
|
+
git add docs/changes/<feature>/proposal.md docs/changes/<feature>/SKILLS.md docs/roadmap.d/ docs/roadmap.md
|
|
214
212
|
git commit -m "docs(<feature>): add spec and promote to planned"
|
|
215
213
|
```
|
|
216
214
|
|
|
217
|
-
|
|
215
|
+
Stage the roadmap by mode: **sharded mode** (`docs/roadmap.d/` present) — stage both `docs/roadmap.d/` (the written shard) and the regenerated `docs/roadmap.md` aggregate; **monolith mode** — stage only `docs/roadmap.md`; **no roadmap** — omit both. Do not skip this step — `harness-execution` commits only implementation files, so a spec uncommitted here stays untracked until someone notices. If a pre-commit hook reformats a file, re-add and re-commit.
|
|
218
216
|
|
|
219
217
|
9. **Write handoff and suggest transition.** After approval:
|
|
220
218
|
|
|
@@ -241,14 +239,21 @@ These flow into `handoff.json` `contextKeywords` field. Select keywords that hel
|
|
|
241
239
|
}
|
|
242
240
|
```
|
|
243
241
|
|
|
244
|
-
|
|
242
|
+
**Choose the next skill with the human — ask in plain text, not via `emit_interaction`** (a `transition` records the handoff; it does not surface the choice). Present both paths and recommend autopilot:
|
|
243
|
+
|
|
244
|
+
> Spec approved. How do you want to build it?
|
|
245
|
+
>
|
|
246
|
+
> - **Autopilot (recommended)** — autonomously chains plan → execute → verify → review, pausing only at decision points. Best when the spec's `## Implementation Order` lays out clear phases.
|
|
247
|
+
> - **Planning** — work the implementation plan interactively before any execution. Choose this when phases are uncertain or you want to drive the breakdown by hand.
|
|
248
|
+
|
|
249
|
+
Record the answer as `<next>` (`autopilot` or `planning`), then call `emit_interaction`:
|
|
245
250
|
|
|
246
251
|
```json
|
|
247
252
|
{
|
|
248
253
|
"type": "transition",
|
|
249
254
|
"transition": {
|
|
250
255
|
"completedPhase": "brainstorming",
|
|
251
|
-
"suggestedNext": "
|
|
256
|
+
"suggestedNext": "<next>",
|
|
252
257
|
"reason": "Spec approved and written to docs/",
|
|
253
258
|
"artifacts": ["<spec path>"],
|
|
254
259
|
"requiresConfirmation": true,
|
|
@@ -269,7 +274,10 @@ These flow into `handoff.json` `contextKeywords` field. Select keywords that hel
|
|
|
269
274
|
}
|
|
270
275
|
```
|
|
271
276
|
|
|
272
|
-
If confirmed
|
|
277
|
+
If confirmed, dispatch by the recorded choice:
|
|
278
|
+
- `autopilot` → invoke harness-autopilot with `--spec <spec path>`.
|
|
279
|
+
- `planning` → invoke harness-planning with the spec path.
|
|
280
|
+
|
|
273
281
|
If declined: stop. The handoff is written for future invocation.
|
|
274
282
|
|
|
275
283
|
---
|
|
@@ -348,11 +356,11 @@ Technical claims about existing code, architecture, or tradeoffs MUST cite evide
|
|
|
348
356
|
- **`harness check-docs`** -- Verify spec does not conflict with existing docs.
|
|
349
357
|
- **`STRATEGY.md` grounding (Phase 1 step 0a)** -- When present at repo root and valid, loaded via the `read_strategy` MCP tool (which the harness MCP server backs with `validateStrategy` + `parseStrategyDoc` + `asStrategyDoc` from `@harness-engineering/core` — projects do not need core installed). Soft-fails when absent or invalid; cites strategy sections in the spec's evidence annotations when present. Boundary with `harness-strategy`: brainstorming READS; `harness-strategy` WRITES. Never modify `STRATEGY.md` from this skill.
|
|
350
358
|
- **Spec location** -- `docs/changes/<feature>/proposal.md`.
|
|
351
|
-
- **Handoff** -- Once approved,
|
|
359
|
+
- **Handoff** -- Once approved, hand off per the human's choice: harness-autopilot (recommended -- autonomous plan → execute → verify → review) or harness-planning (interactive plan only).
|
|
352
360
|
- **Session directory** — When session slug is known, handoff goes to `.harness/sessions/<slug>/handoff.json`. The session directory structure is: `handoff.json`, `state.json`, `artifacts.json` (registry of spec/plan paths and file lists). Do not write to `.harness/handoff.json` in session context.
|
|
353
|
-
- **Spec commit** -- After sign-off, the Phase 4 step 8 commit captures `docs/changes/<feature>/proposal.md`, `docs/changes/<feature>/SKILLS.md`, and the promoted `docs/roadmap.md`
|
|
361
|
+
- **Spec commit** -- After sign-off, the Phase 4 step 8 commit captures `docs/changes/<feature>/proposal.md`, `docs/changes/<feature>/SKILLS.md`, and the promoted roadmap together (in sharded mode: the `docs/roadmap.d/` shard plus the regenerated `docs/roadmap.md` aggregate; in monolith mode: `docs/roadmap.md`) so the spec enters git history at approval, not retroactively. `harness-execution` does not backfill these — see issue #487.
|
|
354
362
|
- **Roadmap promotion** -- After approval (Phase 4 step 7), call `manage_roadmap` action `promote` to transition the named row to `planned` and link the spec atomically with the spec commit. Falls back to `add` (create new row) when the row does not exist; refuses on `in-progress`/`done`/`ambiguous`. Skip silently if no roadmap.
|
|
355
|
-
- **`emit_interaction`** -- End of Phase 4 to
|
|
363
|
+
- **`emit_interaction`** -- End of Phase 4 to record the transition to harness-autopilot or harness-planning (the human picks; default autopilot). The choice itself is asked in plain text -- `emit_interaction` records the confirmed transition, it does not surface the question.
|
|
356
364
|
|
|
357
365
|
#### Requirement Phrasing
|
|
358
366
|
|
|
@@ -539,17 +539,16 @@ gh api repos/{owner}/{repo}/pulls/{pr}/comments \
|
|
|
539
539
|
|
|
540
540
|
### Review Acceptance
|
|
541
541
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
})
|
|
542
|
+
Ask for acceptance directly in your reply. Do NOT route this through `emit_interaction`, `AskUserQuestion`, or any tool. `emit_interaction` records the prompt but does not display it to the human (the client collapses the call to "Called harness" and the rendered text only returns to the model); `AskUserQuestion` is Claude-Code-only and caps headers at 12 chars / 4 options. Plain text in your own message is the only channel that reliably reaches the human across every tool (Claude Code, Cursor, Codex, Gemini CLI). Present it as:
|
|
543
|
+
|
|
544
|
+
```markdown
|
|
545
|
+
Review complete: <Assessment>. Accept review?
|
|
546
|
+
|
|
547
|
+
Context: <N critical, N important, N suggestion findings>
|
|
548
|
+
Impact: Accepting finalizes findings. Approve = ready for merge. Request-changes = fixes needed.
|
|
549
|
+
Risk: <low if approve, high if critical>
|
|
550
|
+
|
|
551
|
+
Proceed? (yes/no)
|
|
553
552
|
```
|
|
554
553
|
|
|
555
554
|
#### Handoff and Transition
|
|
@@ -186,40 +186,37 @@ Three checkpoint types. Each requires pausing execution.
|
|
|
186
186
|
|
|
187
187
|
**`[checkpoint:human-verify]` — Show and Confirm**
|
|
188
188
|
|
|
189
|
-
Stop. Present
|
|
189
|
+
Stop. Present the confirmation in plain text in your reply — do NOT route this through `emit_interaction`, `AskUserQuestion`, or any tool. `emit_interaction` records the prompt but does not display it to the human (the client collapses the call to "Called harness" and the rendered text only returns to the model); `AskUserQuestion` is Claude-Code-only and caps headers at 12 chars / 4 options. Plain text in your own message is the only channel that reliably reaches the human across every tool (Claude Code, Cursor, Codex, Gemini CLI).
|
|
190
190
|
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
risk: "low"
|
|
200
|
-
}
|
|
201
|
-
})
|
|
191
|
+
```markdown
|
|
192
|
+
Task N complete. Output: <summary>. Continue to Task N+1?
|
|
193
|
+
|
|
194
|
+
Context: <test output or diff summary>
|
|
195
|
+
Impact: Continuing proceeds to next task. Declining pauses for review.
|
|
196
|
+
Risk: low
|
|
197
|
+
|
|
198
|
+
Proceed? (yes/no)
|
|
202
199
|
```
|
|
203
200
|
|
|
204
201
|
Wait for human confirmation.
|
|
205
202
|
|
|
206
203
|
**`[checkpoint:decision]` — Present Options and Wait**
|
|
207
204
|
|
|
208
|
-
Stop. Present
|
|
205
|
+
Stop. Present the decision in plain text in your reply — do NOT route this through `emit_interaction`, `AskUserQuestion`, or any tool. `emit_interaction` records the prompt but does not display it to the human (the client collapses the call to "Called harness" and the rendered text only returns to the model); `AskUserQuestion` is Claude-Code-only and caps headers at 12 chars / 4 options. Plain text in your own message is the only channel that reliably reaches the human across every tool (Claude Code, Cursor, Codex, Gemini CLI).
|
|
209
206
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
207
|
+
Present the options as a markdown table so tradeoffs are scannable, state your recommendation, then STOP and wait for the human's reply:
|
|
208
|
+
|
|
209
|
+
```markdown
|
|
210
|
+
### Decision needed: Task N requires a decision: <description>
|
|
211
|
+
|
|
212
|
+
| | A) <option A> | B) <option B> |
|
|
213
|
+
| ---------- | --------------- | --------------- |
|
|
214
|
+
| **Pros** | <option A pros> | <option B pros> |
|
|
215
|
+
| **Cons** | <option A cons> | <option B cons> |
|
|
216
|
+
| **Risk** | low | medium |
|
|
217
|
+
| **Effort** | low | medium |
|
|
218
|
+
|
|
219
|
+
**Recommendation:** A) <option A> (confidence: medium) — <why>.
|
|
223
220
|
```
|
|
224
221
|
|
|
225
222
|
Wait for human choice.
|
|
@@ -378,6 +375,7 @@ Claims about task completion, test results, or code behavior MUST cite evidence:
|
|
|
378
375
|
- **`harness state learn "<message>"`** — Append a learning from CLI.
|
|
379
376
|
- **State/Learnings files** — Session-scoped when session known, otherwise `.harness/`. State updated after every task; learnings append-only.
|
|
380
377
|
- **Roadmap claim** — Phase 2 Step 0: `manage_roadmap update` with `status: in-progress` + `assignee: <currentUser>` claims the item at execution start (the assignee = "who is executing" invariant). Stop if `currentUser` is unresolvable. Marking the row `done` later auto-clears the assignee via the lifecycle `setStatus` chokepoint — never leave a non-in-progress row assigned (RMH005).
|
|
378
|
+
- **Auto-done (do NOT hand-mark rows done)** — A row reaches `done` automatically when the implementing PR merges and closes its linked issue: the merge-triggered auto-done reconciler flips exactly that shard via `External-ID` (CI Action authoritative; `harness roadmap reconcile` is the offline fallback). Execution should claim the row `in-progress` and let the merge drive it to `done` — do not call `manage_roadmap update status:done` by hand. See knowledge [`merge-triggered-auto-done.md`](../../../../docs/knowledge/roadmap/merge-triggered-auto-done.md). In sharded mode (`docs/roadmap.d/` present) the claim writes one shard and regenerates the aggregate.
|
|
381
379
|
- **Roadmap sync** — After plan completion, `manage_roadmap sync` with `apply: true`. Mandatory when roadmap exists. No `force_sync: true`.
|
|
382
380
|
- **`emit_interaction`** — Auto-transition to harness-verification at plan completion.
|
|
383
381
|
|
|
@@ -66,7 +66,7 @@ Before running sub-phases, resolve the effective integration tier:
|
|
|
66
66
|
Tier escalated from `small` to `medium`: 8 new exports detected.
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
Inform the human and get acknowledgment in plain text in your reply (do NOT route this through `emit_interaction` or `AskUserQuestion` — they record the prompt but do not display it to the human, so they won't see it).
|
|
70
70
|
|
|
71
71
|
---
|
|
72
72
|
|
|
@@ -213,7 +213,7 @@ Skip this sub-phase for `small` tier or `fast` rigor. For medium and large tiers
|
|
|
213
213
|
<What follows from this decision -- positive, negative, and neutral?>
|
|
214
214
|
```
|
|
215
215
|
|
|
216
|
-
d. **Present for review.** In `thorough` rigor, present each ADR draft
|
|
216
|
+
d. **Present for review.** In `thorough` rigor, present each ADR draft in plain text in your reply and wait for human approval — do NOT route it through `emit_interaction` or `AskUserQuestion`, which record the prompt but do not display it to the human (the client collapses the call to "Called harness" and the text only returns to the model). In `standard` rigor, auto-approve but log the draft for review.
|
|
217
217
|
|
|
218
218
|
#### Knowledge Graph Enrichment (medium + large tiers)
|
|
219
219
|
|
|
@@ -266,7 +266,7 @@ Skip this sub-phase for `small` tier or `fast` rigor. For medium and large tiers
|
|
|
266
266
|
|
|
267
267
|
---
|
|
268
268
|
|
|
269
|
-
### Sub-Phase 3: UPDATE (medium
|
|
269
|
+
### Sub-Phase 3: UPDATE (medium and large tiers)
|
|
270
270
|
|
|
271
271
|
Report progress: `**[UPDATE]** Checking project metadata updates`
|
|
272
272
|
|
|
@@ -364,22 +364,24 @@ After all applicable sub-phases complete, produce the combined integration repor
|
|
|
364
364
|
|
|
365
365
|
Immediately invoke harness-code-review without waiting for user input.
|
|
366
366
|
|
|
367
|
-
4. **On FAIL:** Do NOT emit a transition. Report incomplete items with fix instructions
|
|
367
|
+
4. **On FAIL:** Do NOT emit a transition. Report incomplete items with fix instructions, then ask the human how to proceed in plain text.
|
|
368
368
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
369
|
+
**Ask directly in your reply. Do NOT route the question through `emit_interaction`, `AskUserQuestion`, or any tool.** `emit_interaction` records the prompt but does not display it to the human — the client collapses the call to "Called harness" and the rendered text only returns to the model, so the human sees nothing and you end up narrating a question they cannot answer. `AskUserQuestion` is Claude-Code-only and caps headers at 12 chars / 4 options. Plain text in your own message is the only channel that reliably reaches the human across every tool (Claude Code, Cursor, Codex, Gemini CLI).
|
|
370
|
+
|
|
371
|
+
Present the options as a markdown table, state your recommendation, then STOP and wait for the human's reply:
|
|
372
|
+
|
|
373
|
+
```markdown
|
|
374
|
+
### Decision needed: Integration failed. <N> items incomplete. How to proceed?
|
|
375
|
+
|
|
376
|
+
| | fix | skip | stop |
|
|
377
|
+
| ---------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------ | ------------------------- |
|
|
378
|
+
| **What** | Re-enter EXECUTE with integration-specific fix tasks, then re-VERIFY, re-INTEGRATE | Record decision and proceed to REVIEW (human override) | Save state and exit |
|
|
379
|
+
| **Pros** | Closes gaps before review | Unblocks progress immediately | Preserves state for later |
|
|
380
|
+
| **Cons** | Another execute/verify cycle | Ships with known gaps | No forward progress |
|
|
381
|
+
| **Risk** | Low | Medium | Low |
|
|
382
|
+
| **Effort** | Medium | Low | Low |
|
|
383
|
+
|
|
384
|
+
**Recommendation:** fix (confidence: high) — fixing integration gaps now prevents review rework.
|
|
383
385
|
```
|
|
384
386
|
|
|
385
387
|
- **fix:** Record fix tasks in handoff. The autopilot re-enters EXECUTE with those tasks.
|
|
@@ -449,7 +451,7 @@ Every pass/fail assertion in the integration report MUST include concrete eviden
|
|
|
449
451
|
- **`harness check-deps`** -- Run during WIRE if new modules were added.
|
|
450
452
|
- **`ingest_source`** -- Run during MATERIALIZE to enrich knowledge graph with decision nodes.
|
|
451
453
|
- **`manage_roadmap`** -- Run during UPDATE to sync roadmap status. Use `sync` with `apply: true`.
|
|
452
|
-
- **`emit_interaction`** -- Tier escalation
|
|
454
|
+
- **`emit_interaction`** -- Used only for the transition to REVIEW on pass. Tier escalation, ADR review (thorough mode), and fail/skip/stop decisions are asked in plain text in your reply.
|
|
453
455
|
- **Session directory** -- `.harness/sessions/<slug>/` contains all report files. Do not write to global `.harness/` when session slug is known.
|
|
454
456
|
|
|
455
457
|
## Success Criteria
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# Harness Maintenance Pipeline
|
|
2
|
+
|
|
3
|
+
> One on-demand entry point for project maintenance. Runs the checks that are actually overdue, triages what needs attention, and asks you — in plain text — which to fix. A thin wrapper over `harness maintenance run`; it owns no state of its own.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
- You want to answer "which maintenance did I forget to run?" without standing up an orchestrator.
|
|
8
|
+
- At a milestone or before a release, to sweep overdue health checks (dead code, doc drift, dependency health, security, hotspots, project health).
|
|
9
|
+
- When you want a report first and an explicit, opt-in fix step — never a surprise PR.
|
|
10
|
+
- NOT for running a single known check — call that skill or `harness maintenance run --only <id>` directly.
|
|
11
|
+
- NOT for the autonomous cron fix-and-PR path — that is the orchestrator scheduler's job; this is the human-invoked, report-first path.
|
|
12
|
+
|
|
13
|
+
## What this skill does NOT do
|
|
14
|
+
|
|
15
|
+
- It does not implement any maintenance check, scheduler, or registry — the CLI and the existing 22-task registry are the single source of truth.
|
|
16
|
+
- It does not write artifacts. The CLI writes `.harness/maintenance/last-run-summary.json` and records history; this skill only reads and relays.
|
|
17
|
+
- It does not open PRs. Fixes are opt-in via the explicit fix step; when a backend is configured, `--fix` dispatches a real agent that commits to the worktree (no PR). When no backend is configured it honestly skips (see Phase 3 / FIX).
|
|
18
|
+
|
|
19
|
+
## Process
|
|
20
|
+
|
|
21
|
+
### Phase 1: SWEEP — run the overdue report
|
|
22
|
+
|
|
23
|
+
1. Run the report-mode sweep and capture stdout:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
harness maintenance run --json
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
No flags = overdue, sweep-eligible tasks only, report mode (no PRs). Capture both stdout (the JSON report) and the exit code.
|
|
30
|
+
|
|
31
|
+
2. Parse stdout as a `ConsolidatedReport`:
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
// shape emitted by the CLI (packages/cli/src/commands/maintenance-run.ts)
|
|
35
|
+
{
|
|
36
|
+
generatedAt: string;
|
|
37
|
+
mode: 'report' | 'fix';
|
|
38
|
+
fix: boolean;
|
|
39
|
+
exitCode: 0 | 1;
|
|
40
|
+
tasks: Array<{
|
|
41
|
+
taskId: string;
|
|
42
|
+
status: 'success' | 'failure' | 'skipped' | 'no-issues';
|
|
43
|
+
findings: number; // a COUNT — there is no per-finding severity
|
|
44
|
+
fixed: number;
|
|
45
|
+
prUrl: string | null;
|
|
46
|
+
summary: string; // 'clean' | `${n} finding(s)` | error text
|
|
47
|
+
error?: string;
|
|
48
|
+
}>;
|
|
49
|
+
overdueNowCurrent: string[];
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
If capturing stdout is awkward, read the same object from `.harness/maintenance/last-run-summary.json` with the Read tool.
|
|
54
|
+
|
|
55
|
+
3. Read the **exit code**: `0` = the sweep completed (findings are NOT failures); `1` = at least one check failed to execute; `2` = invalid invocation (a bug in how this skill called the CLI — fix the invocation, do not report it as a finding).
|
|
56
|
+
|
|
57
|
+
4. If `tasks` is empty, tell the human "All maintenance is current — nothing overdue." and stop. Do not invent work.
|
|
58
|
+
|
|
59
|
+
### Phase 2: TRIAGE — present a human-readable summary
|
|
60
|
+
|
|
61
|
+
There is no per-finding severity in the report, so triage by **status** then **findings count** (rows arrive pre-sorted failures-first, then findings-descending). Bucket the tasks:
|
|
62
|
+
|
|
63
|
+
- **Failed to execute** — `status === 'failure'`. The check itself crashed; surface `summary`/`error`. These are the most urgent: a finding you cannot see is worse than one you can.
|
|
64
|
+
- **Needs attention** — `findings > 0` (and not a failure). Order by `findings` descending. Derive a coarse domain from the task id (e.g. `dead-code`, `doc-drift`, `dependency-health`, `security`, `hotspots`, `project-health`).
|
|
65
|
+
- **Skipped (couldn't run)** — `status === 'skipped'`. A precondition gate was not met, so the check **never ran** — it is NOT clean, it has simply told you nothing. Report these distinctly from clean tasks so the human knows coverage was incomplete (and can decide whether the precondition is worth satisfying). Summarize as a count and, if useful, surface `summary` for why it was gated.
|
|
66
|
+
- **Clean** — `status` is `no-issues`/`success` with `findings === 0`. The check ran and found nothing. Summarize as a count ("8 checks clean"); do not enumerate unless asked. Do NOT fold `skipped` tasks in here — a gated check that never ran is not a clean result.
|
|
67
|
+
|
|
68
|
+
Render a compact summary, for example:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
Maintenance sweep (report mode) — 18 overdue tasks ran, exit 0
|
|
72
|
+
|
|
73
|
+
Failed to execute (1):
|
|
74
|
+
stale-constraints — check crashed: <summary>
|
|
75
|
+
|
|
76
|
+
Needs attention (3):
|
|
77
|
+
dead-code — 12 finding(s)
|
|
78
|
+
doc-drift — 4 finding(s)
|
|
79
|
+
dependency-health — 1 finding(s)
|
|
80
|
+
|
|
81
|
+
Skipped — couldn't run (1): license-audit (precondition not met)
|
|
82
|
+
|
|
83
|
+
Clean (13): project-health, hotspots, security, …
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
If `overdueNowCurrent` is non-empty, add a one-line footer: "N tasks were overdue and are now marked current."
|
|
87
|
+
|
|
88
|
+
### Phase 3: FIX — ask in plain text, then opt in
|
|
89
|
+
|
|
90
|
+
1. **Ask the human in plain text, in your own reply.** Do NOT use `emit_interaction` and do NOT use `AskUserQuestion` for this — those channels do not reliably reach the human (an `emit_interaction` ask collapses to "Called harness" and the human never sees the question). Write the question as ordinary text, listing the actionable task ids (the "Failed to execute" and "Needs attention" buckets) and asking which, if any, to fix. For example:
|
|
91
|
+
|
|
92
|
+
> These tasks have findings: `dead-code` (12), `doc-drift` (4), `dependency-health` (1). Which would you like me to fix? Reply with a comma-separated list of task ids, "all", or "none".
|
|
93
|
+
|
|
94
|
+
Then stop and wait for the human's reply. Do not proceed to a fix without an explicit answer.
|
|
95
|
+
|
|
96
|
+
2. **If the human picks tasks**, re-invoke the CLI in fix mode, scoped to exactly those ids — and capture **both** streams separately:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
harness maintenance run --only <comma,separated,ids> --fix --json
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
stdout stays a clean, parseable `ConsolidatedReport` (parse it as JSON, same shape as the sweep). Any honesty notice is written to **stderr**, NOT stdout — so capture stderr too (e.g. redirect to a separate file/buffer) and inspect it. If you only read stdout you will silently drop the notice; if you merge stderr into stdout you will break `JSON.parse`. Keep them apart: JSON ← stdout, notice ← stderr.
|
|
103
|
+
|
|
104
|
+
3. **Relay the result honestly.** `--fix` threads fix mode through the **real agent dispatcher** (#679): when a backend is configured for the default maintenance backend, the agent runs and commits its fixes directly to the worktree — there is **no PR** (`prUrl` stays `null`), and `fixed` is the real commit count. When **no** backend is configured (a plain checkout with no `agent.backends` in `harness.orchestrator.md`), `--fix` does not crash and does not pretend to work — it skips dispatch and prints this notice to **stderr** (which is why step 2 captures stderr separately):
|
|
105
|
+
|
|
106
|
+
> `--fix: no agent backend configured for maintenance dispatch — dispatch was skipped and nothing was fixed. Configure agent.backends in harness.orchestrator.md (and maintenance.aiBackend), or run maintenance via the orchestrator.`
|
|
107
|
+
|
|
108
|
+
Inspect the captured stderr for that notice and, if present, surface it verbatim. Report what the CLI actually did (the stdout report's `fixed` counts; `prUrl` is always `null` — there is no PR) — never claim a fix was applied or a PR opened when the report does not show one.
|
|
109
|
+
|
|
110
|
+
4. **If the human picks "none"**, stop. The report stands on its own.
|
|
111
|
+
|
|
112
|
+
## Harness Integration
|
|
113
|
+
|
|
114
|
+
- **`harness maintenance run --json`** — the report-mode sweep this skill wraps. Runs overdue, sweep-eligible tasks only and emits the `ConsolidatedReport` to stdout (also written to `.harness/maintenance/last-run-summary.json`). This is the single entry point — the skill adds no execution path of its own.
|
|
115
|
+
- **`harness maintenance run --only <ids> --fix --json`** — the opt-in fix leg, scoped to the ids the human picked. Threads `mode: 'fix'` through the same `TaskRunner`, using the real agent dispatcher (#679). Capture stdout (the JSON report) and stderr **separately**: when no agent backend is configured it prints the honest no-backend skip notice to stderr (stdout stays clean JSON) — inspect that captured stderr and relay any notice verbatim.
|
|
116
|
+
- **`harness maintenance list` / `harness maintenance show <id>`** — inspect the registry (the 22-task source of truth) when the human wants to know what a task id means before choosing to fix it.
|
|
117
|
+
- **Read tool on `.harness/maintenance/last-run-summary.json`** — the documented fallback parse path if capturing `--json` stdout is awkward on a given platform. The skill never writes this file; the CLI owns it.
|
|
118
|
+
|
|
119
|
+
## Gates
|
|
120
|
+
|
|
121
|
+
- **Plain-text ask only.** The "which to fix?" question must be ordinary text in your reply. Never route it through `emit_interaction` or `AskUserQuestion`.
|
|
122
|
+
- **Report before fix, always.** Never pass `--fix` on the first sweep. Fix is opt-in after the human sees the report and chooses.
|
|
123
|
+
- **No invented findings.** Report only what the `ConsolidatedReport` contains. If `tasks` is empty, say so and stop.
|
|
124
|
+
- **No self-persistence.** Do not write `.harness/maintenance/*` or any report file — the CLI owns artifacts.
|
|
125
|
+
- **Honest fix status.** Relay what the CLI reports: real `fixed` counts when a backend dispatched, or the no-backend skip notice (if it appears on stderr) when it did not. `prUrl` is always `null` — the agent commits to the worktree; never imply a PR was opened.
|
|
126
|
+
|
|
127
|
+
## Success Criteria
|
|
128
|
+
|
|
129
|
+
- Ran `harness maintenance run --json`, parsed the consolidated report, and read the exit code.
|
|
130
|
+
- Presented a triaged summary bucketed by status (failed / needs-attention / clean) and ordered by findings count.
|
|
131
|
+
- Asked the human in plain text which tasks to fix, and waited for a reply.
|
|
132
|
+
- On opt-in, re-invoked `--only <ids> --fix` and relayed the result (real `fixed` counts, or the honest no-backend skip notice if it appeared) verbatim.
|
|
133
|
+
- Wrote no files of its own.
|
|
134
|
+
|
|
135
|
+
## Examples
|
|
136
|
+
|
|
137
|
+
### Example: Milestone sweep with mixed results
|
|
138
|
+
|
|
139
|
+
The human invokes the skill before tagging a release.
|
|
140
|
+
|
|
141
|
+
1. **SWEEP:** Run `harness maintenance run --json`. Exit code `0`; `tasks` has 18 rows; `overdueNowCurrent` lists 18 ids.
|
|
142
|
+
2. **TRIAGE:** Bucket the pre-sorted rows:
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
Maintenance sweep (report mode) — 18 overdue tasks ran, exit 0
|
|
146
|
+
|
|
147
|
+
Failed to execute (1):
|
|
148
|
+
stale-constraints — check crashed: cannot read .harness/constraints.json
|
|
149
|
+
|
|
150
|
+
Needs attention (3):
|
|
151
|
+
dead-code — 12 finding(s)
|
|
152
|
+
doc-drift — 4 finding(s)
|
|
153
|
+
dependency-health — 1 finding(s)
|
|
154
|
+
|
|
155
|
+
Clean (14): project-health, hotspots, security, …
|
|
156
|
+
18 tasks were overdue and are now marked current.
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
3. **FIX (plain-text ask):** In the reply, write: "These tasks have findings: `dead-code` (12), `doc-drift` (4), `dependency-health` (1), plus `stale-constraints` failed to execute. Which would you like me to fix? Reply with a comma-separated list of task ids, \"all\", or \"none\"." Then stop and wait.
|
|
160
|
+
4. The human replies `dead-code,doc-drift`. Run `harness maintenance run --only dead-code,doc-drift --fix`. With a backend configured, the agent dispatches and commits its fixes to the worktree — report the real `fixed` counts from the report (`prUrl: null` — there is no PR). If no backend is configured, the CLI prints to stderr: `--fix: no agent backend configured for maintenance dispatch — dispatch was skipped and nothing was fixed. Configure agent.backends in harness.orchestrator.md (and maintenance.aiBackend), or run maintenance via the orchestrator.` Relay that verbatim and report `fixed: 0`, `prUrl: null` — do not claim a fix or PR.
|
|
161
|
+
|
|
162
|
+
### Example: Nothing overdue
|
|
163
|
+
|
|
164
|
+
Run `harness maintenance run --json`. On the nothing-overdue happy path stdout is still a parseable `ConsolidatedReport` whose `tasks` is an **empty array** (`tasks: []`, `exitCode: 0`) — NOT a plain `All maintenance current.` sentinel (that human string is emitted only on the non-`--json` path). So `JSON.parse(stdout)` succeeds; read `tasks.length === 0`. Tell the human "All maintenance is current — nothing overdue." and stop. Do not invent work or run `--fix`.
|
|
165
|
+
|
|
166
|
+
## Rationalizations to Reject
|
|
167
|
+
|
|
168
|
+
| Rationalization | Reality |
|
|
169
|
+
| ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
170
|
+
| "I'll just run `--fix` directly to save a round-trip." | Report-first is the whole point. A surprise fix on an on-demand sweep is exactly the hazard this path avoids. |
|
|
171
|
+
| "I'll ask via `emit_interaction` so it's structured." | That ask never reaches the human — it collapses to "Called harness". Ask in plain text. |
|
|
172
|
+
| "The report shows findings, so I'll say I fixed them." | `--fix` only fixes when a backend dispatched; relay what the CLI reports (real `fixed` counts, or the no-backend skip notice). `prUrl` is always `null`. Do not overclaim. |
|
|
173
|
+
| "There's no severity field, so I'll assign my own." | Triage by the status + findings count the report actually provides. Do not fabricate a severity taxonomy. |
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: harness-maintenance-pipeline
|
|
2
|
+
version: '1.0.0'
|
|
3
|
+
description: On-demand, report-first maintenance sweep — runs overdue checks via `harness maintenance run`, triages findings, and asks the human in plain text before dispatching any fix
|
|
4
|
+
stability: draft
|
|
5
|
+
cognitive_mode: analytical-reporter
|
|
6
|
+
triggers:
|
|
7
|
+
- manual
|
|
8
|
+
- on_milestone
|
|
9
|
+
platforms:
|
|
10
|
+
- claude-code
|
|
11
|
+
- cursor
|
|
12
|
+
- codex
|
|
13
|
+
- gemini-cli
|
|
14
|
+
tools:
|
|
15
|
+
- Bash
|
|
16
|
+
- Read
|
|
17
|
+
cli:
|
|
18
|
+
command: harness skill run harness-maintenance-pipeline
|
|
19
|
+
args:
|
|
20
|
+
- name: path
|
|
21
|
+
description: Project root path
|
|
22
|
+
required: false
|
|
23
|
+
mcp:
|
|
24
|
+
tool: run_skill
|
|
25
|
+
input:
|
|
26
|
+
skill: harness-maintenance-pipeline
|
|
27
|
+
path: string
|
|
28
|
+
type: flexible
|
|
29
|
+
tier: 2
|
|
30
|
+
phases:
|
|
31
|
+
- name: sweep
|
|
32
|
+
description: Run `harness maintenance run --json` (overdue, report mode) and parse the consolidated report
|
|
33
|
+
required: true
|
|
34
|
+
- name: triage
|
|
35
|
+
description: Present a human-readable summary bucketed by status and findings count
|
|
36
|
+
required: true
|
|
37
|
+
- name: fix
|
|
38
|
+
description: Ask the human in plain text which tasks to fix, then re-invoke `--only <ids> --fix` and relay the result
|
|
39
|
+
required: false
|
|
40
|
+
state:
|
|
41
|
+
persistent: false
|
|
42
|
+
files: []
|
|
43
|
+
depends_on: []
|
|
@@ -35,6 +35,8 @@
|
|
|
35
35
|
|
|
36
36
|
4. **Read `.harness/state.json`** if it exists. This reveals what was happening in the last session — current phase, active task, any blockers that were recorded.
|
|
37
37
|
|
|
38
|
+
5. **Detect the roadmap layout.** If `docs/roadmap.d/` exists the project uses the **sharded** roadmap: per-row shards `docs/roadmap.d/<slug>.md` (plus `_meta.md`) are canonical and `docs/roadmap.md` is a **generated** `merge=ours` aggregate (do not hand-edit it). New contributors must run the one-time per-clone setup so generated-file merges behave: `git config merge.ours.driver true` (the `.gitattributes merge=ours` entry is inert without it — `harness validate` warns clones that have not run it). Surface this in "Getting Started". If only `docs/roadmap.md` exists, the project is monolith; if neither, it is file-less or uninitialized. See the adoption guide `docs/guides/roadmap-sharding.md`.
|
|
39
|
+
|
|
38
40
|
### Phase 2: MAP — Understand the Codebase Structure
|
|
39
41
|
|
|
40
42
|
Use `code_outline` to get structural overviews of key modules (functions, classes, exports) without reading full source files. Use `code_search` to locate patterns, symbols, or conventions across the codebase.
|