@harness-engineering/cli 3.0.1 → 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 +59 -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 +40 -43
- 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 +59 -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 +40 -43
- 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 +59 -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 +40 -43
- 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 +59 -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 +40 -43
- 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-XOJE5ETA.js → agents-md-7OSNWU52.js} +2 -2
- package/dist/{architecture-JEZPJ725.js → architecture-2XYGJGT3.js} +3 -3
- package/dist/{assess-project-RHXOQNMM.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-GNDOMS35.js → check-phase-gate-46U5AAXE.js} +4 -3
- package/dist/{chunk-MGUPSE6D.js → chunk-363V6GPR.js} +5 -5
- package/dist/{chunk-HEIMJJI4.js → chunk-6NCREWWM.js} +2 -2
- package/dist/{chunk-XFU6SB2Q.js → chunk-6YXCZV33.js} +2171 -924
- package/dist/{chunk-HWTUUQOW.js → chunk-AK67S3O4.js} +3 -3
- package/dist/{chunk-BYVT5LVO.js → chunk-BV45354Q.js} +3 -3
- package/dist/{chunk-WWEVS7RO.js → chunk-ERILXQBP.js} +1181 -486
- package/dist/{chunk-UX3PQKVZ.js → chunk-FZ4Q73HA.js} +1 -1
- package/dist/{chunk-Z4AWEIBY.js → chunk-GXCPDAS5.js} +3 -3
- package/dist/{chunk-XX4OLNWQ.js → chunk-HMW3C5DP.js} +2 -2
- package/dist/{chunk-PC2R5RUJ.js → chunk-HXMAIVV2.js} +1 -1
- package/dist/{chunk-QBC7DI4Q.js → chunk-IYWT3JJW.js} +1 -1
- package/dist/{chunk-N24HCQA4.js → chunk-KLPX55TI.js} +3015 -1138
- package/dist/{chunk-527G27VI.js → chunk-MSBJ445U.js} +4 -4
- package/dist/{chunk-NWLGL3IR.js → chunk-MYVTYFQD.js} +2 -2
- package/dist/{chunk-KAJOS3BA.js → chunk-PHX45JYN.js} +5 -9
- package/dist/{chunk-6WQCLCBO.js → chunk-S2RQPPL6.js} +1 -1
- package/dist/chunk-SPE7P4GL.js +61 -0
- package/dist/{chunk-YQSYCBAH.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-GSP2XIVS.js → chunk-VTU3QOJT.js} +48 -4
- package/dist/{chunk-3ISHDWO7.js → chunk-VTUINXWR.js} +1 -1
- package/dist/{chunk-27AJKSQY.js → chunk-WBVCN35T.js} +1 -1
- package/dist/{chunk-ONCPJGHY.js → chunk-WL3O2PKJ.js} +6 -6
- package/dist/{chunk-GGKRA7A7.js → chunk-XFHZ7GCI.js} +1 -1
- package/dist/chunk-Y6SUQC32.js +9 -0
- package/dist/{chunk-DE5U6KOL.js → chunk-ZEYAOYJL.js} +1 -1
- package/dist/{ci-workflow-ORZ4F45F.js → ci-workflow-XJN4UO3Q.js} +2 -2
- package/dist/{dist-LHINSVK4.js → dist-IPVFYGY2.js} +85 -15
- package/dist/{docs-AU3DXFFO.js → docs-RSFZTNPG.js} +3 -3
- package/dist/{engine-6GPWOYQH.js → engine-DJIHY4JT.js} +2 -2
- package/dist/{entropy-VLKDRMRT.js → entropy-EAEKJKRM.js} +2 -2
- package/dist/{feedback-YXYY44ZC.js → feedback-JT5X3DBC.js} +1 -1
- package/dist/{generate-agent-definitions-XIHQPKG3.js → generate-agent-definitions-CC6KED3E.js} +4 -4
- package/dist/hooks/adoption-tracker.js +6 -5
- package/dist/hooks/format-check.js +202 -0
- package/dist/hooks/protect-config.js +15 -5
- package/dist/hooks/quality-warner.js +32 -0
- package/dist/hooks/strict-quality-gate.js +48 -0
- 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-YAN56MT3.js → loader-UWNVTYBY.js} +2 -2
- package/dist/{mcp-RK3SFVYB.js → mcp-TCLNK7HG.js} +18 -17
- package/dist/{performance-64DPTLLQ.js → performance-R6O3N3UB.js} +3 -3
- package/dist/{review-pipeline-NENG6LW7.js → review-pipeline-MOOWXWSQ.js} +2 -2
- package/dist/{runtime-FFIIRT2T.js → runtime-RIWQUKBQ.js} +2 -2
- package/dist/{security-3PIBN35B.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-7IAF2ES3.js → validate-IUAV7MOU.js} +3 -3
- package/dist/{validate-cross-check-QPSAOZKD.js → validate-cross-check-M2ZM6RFY.js} +2 -2
- package/package.json +7 -7
- package/dist/hooks/quality-gate.js +0 -131
|
@@ -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.
|
|
@@ -95,44 +95,21 @@ Store the parsed skill list for use in Phase 2 task annotation.
|
|
|
95
95
|
|
|
96
96
|
**Read-only constraint:** Steps 1-6 above are research and analysis. Do not propose task structure, file organization, or implementation approaches during SCOPE. Record what must be true (observable truths) and what you do not know (uncertainties). Solutions belong in DECOMPOSE.
|
|
97
97
|
|
|
98
|
-
When scope is ambiguous,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
label: "B) Defer Y to a follow-up plan",
|
|
116
|
-
pros: ["Keeps current plan focused", "Ship sooner"],
|
|
117
|
-
cons: ["Y remains unhandled", "May need rework when Y is added"],
|
|
118
|
-
risk: "low",
|
|
119
|
-
effort: "low"
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
label: "C) Update the spec first",
|
|
123
|
-
pros: ["Design is complete before planning", "No surprises during execution"],
|
|
124
|
-
cons: ["Blocks planning until spec is updated", "Extra round-trip"],
|
|
125
|
-
risk: "low",
|
|
126
|
-
effort: "medium"
|
|
127
|
-
}
|
|
128
|
-
],
|
|
129
|
-
recommendation: {
|
|
130
|
-
optionIndex: 1,
|
|
131
|
-
reason: "Keeping the current plan focused reduces risk. Y can be addressed in a follow-up.",
|
|
132
|
-
confidence: "medium"
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
})
|
|
98
|
+
When scope is ambiguous, ask 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).
|
|
99
|
+
|
|
100
|
+
Present the choice as a markdown table so tradeoffs are scannable, state your recommendation, then STOP and wait for the human's reply:
|
|
101
|
+
|
|
102
|
+
```markdown
|
|
103
|
+
### Decision needed: The spec mentions X but does not define behavior for Y. Should we:
|
|
104
|
+
|
|
105
|
+
| | A) Include Y in this plan | B) Defer Y to a follow-up plan | C) Update the spec first |
|
|
106
|
+
| ---------- | ------------------------------------------------------- | ---------------------------------------------------- | ----------------------------------------------------------------- |
|
|
107
|
+
| **Pros** | Complete feature in one pass; no follow-up coordination | Keeps current plan focused; ship sooner | Design is complete before planning; no surprises during execution |
|
|
108
|
+
| **Cons** | Increases scope and time; may delay delivery | Y remains unhandled; may need rework when Y is added | Blocks planning until spec is updated; extra round-trip |
|
|
109
|
+
| **Risk** | Medium | Low | Low |
|
|
110
|
+
| **Effort** | High | Low | Medium |
|
|
111
|
+
|
|
112
|
+
**Recommendation:** B) Defer Y to a follow-up plan (confidence: medium) — keeping the current plan focused reduces risk; Y can be addressed in a follow-up.
|
|
136
113
|
```
|
|
137
114
|
|
|
138
115
|
#### EARS Requirement Patterns
|
|
@@ -223,7 +200,7 @@ Report progress: `**[Phase 2/4]** DECOMPOSE — mapping file structure and creat
|
|
|
223
200
|
**Estimated total:** 8 tasks, ~33 minutes
|
|
224
201
|
```
|
|
225
202
|
|
|
226
|
-
**Approval gate:**
|
|
203
|
+
**Approval gate:** Ask in plain text in your reply — do NOT route this through `emit_interaction` or `AskUserQuestion` (they do not display to the human; `emit_interaction` collapses to "Called harness" and `AskUserQuestion` is Claude-Code-only). Ask directly: "Approve skeleton direction?" and wait. If approved, proceed to step 3. If rejected, revise and re-present.
|
|
227
204
|
|
|
228
205
|
3. **Decompose into atomic tasks.** Each task must:
|
|
229
206
|
- Be completable in 2-5 minutes, fit in a single context window
|
|
@@ -313,7 +290,7 @@ Report progress: `**[Phase 2/4]** DECOMPOSE — mapping file structure and creat
|
|
|
313
290
|
|
|
314
291
|
10. **Write session summary (if session is known).** Call `writeSessionSummary` with skill, status, plan path, keyContext, nextStep. Skip if no session slug.
|
|
315
292
|
|
|
316
|
-
11. **Request plan sign-off
|
|
293
|
+
11. **Request plan sign-off in plain text.** Ask directly in your reply — do NOT route this through `emit_interaction` or `AskUserQuestion` (the human will not see it; `emit_interaction` collapses to "Called harness" and `AskUserQuestion` is Claude-Code-only). Present the plan path, task count, and time estimate, then ask: "Proceed? (yes/no)" and wait for the reply.
|
|
317
294
|
|
|
318
295
|
12. **Suggest transition to execution.** After approval, call `emit_interaction` with type: `transition`, `completedPhase: "planning"`, `suggestedNext: "execution"`, `requiresConfirmation: true`. Include `qualityGate` with checks: plan-written, harness-validate, observable-truths-traced, human-approved. If confirmed: invoke harness-execution. If declined: stop (handoff already written).
|
|
319
296
|
|
|
@@ -35,7 +35,7 @@ Read `references/interview.md` for the SMART pushback rules and the READ-WRITE-D
|
|
|
35
35
|
- If `name` is non-null, confirm it as the product name; otherwise prompt.
|
|
36
36
|
- For each `keyMetric`, walk it through the SMART bar in step 4.
|
|
37
37
|
|
|
38
|
-
2. **Pick the lookback default.**
|
|
38
|
+
2. **Pick the lookback default.** Ask in plain text — present numbered options `["24h", "7d", "30d", "custom"]` and wait (do NOT use `emit_interaction`/`AskUserQuestion`; the human won't see it — it renders only to the model and the client collapses the call to "Called harness"). Default `24h` per spec.
|
|
39
39
|
|
|
40
40
|
3. **Identify the primary engagement event** (e.g. `session_started`). Apply the SMART bar. If the user can't name one, set `null` and add a pending entry. Record the event name in `primaryEvent`.
|
|
41
41
|
|
|
@@ -25,6 +25,23 @@ If the human has not seen and approved the milestone groupings and feature list,
|
|
|
25
25
|
|
|
26
26
|
---
|
|
27
27
|
|
|
28
|
+
### Storage mode: monolith vs sharded
|
|
29
|
+
|
|
30
|
+
The roadmap has two physical layouts, auto-detected (not configured) by the presence of `docs/roadmap.d/`:
|
|
31
|
+
|
|
32
|
+
- **Monolith** — a single `docs/roadmap.md` aggregate is canonical (legacy default).
|
|
33
|
+
- **Sharded** — per-row shards `docs/roadmap.d/<slug>.md` (plus `_meta.md`) are canonical, and `docs/roadmap.md` is a generated `merge=ours` aggregate. New `harness init` projects are sharded by default.
|
|
34
|
+
|
|
35
|
+
In sharded mode a write patches a **single shard** (conflict-free by construction) and **regenerates the aggregate** — so when committing a roadmap change, stage both `docs/roadmap.d/` and the regenerated `docs/roadmap.md`. Read/write only through `manage_roadmap` / the `RoadmapStore`; never parse the aggregate for content (read-source invariant R, ADR 0050). Subcommands:
|
|
36
|
+
|
|
37
|
+
- `harness roadmap shard` — adopt sharding (split the monolith into shards), reversible with `harness roadmap unshard` (semantic round-trip).
|
|
38
|
+
- `harness roadmap regen` — regenerate the aggregate from the shards (the fix when `harness validate` warns the aggregate has drifted).
|
|
39
|
+
- `harness roadmap reconcile` — offline merge-triggered auto-done (flip closed-issue rows to `done`).
|
|
40
|
+
|
|
41
|
+
**Stop hand-marking rows `done`** — rows reach `done` automatically when the implementing PR merges (auto-done reconciler; see knowledge [`merge-triggered-auto-done.md`](../../../../docs/knowledge/roadmap/merge-triggered-auto-done.md)). See also the adoption guide [`docs/guides/roadmap-sharding.md`](../../../../docs/guides/roadmap-sharding.md).
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
28
45
|
### Command: `--create` -- Bootstrap Roadmap
|
|
29
46
|
|
|
30
47
|
#### Phase 1: SCAN -- Discover Artifacts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Harness Roadmap Pilot
|
|
2
2
|
|
|
3
|
-
> AI-assisted selection of the next highest-impact unblocked roadmap item. Scores candidates, recommends one,
|
|
3
|
+
> AI-assisted selection of the next highest-impact unblocked roadmap item. Scores candidates, recommends one, and transitions to the appropriate next skill. Selection does NOT assign — the `assignee` field names who is _executing_, and is written at execution start (harness-execution), not at selection.
|
|
4
4
|
|
|
5
5
|
## When to Use
|
|
6
6
|
|
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
|
|
15
15
|
### Iron Law
|
|
16
16
|
|
|
17
|
-
**Never
|
|
17
|
+
**Never transition without the human confirming the recommendation first. Selection never writes `assignee`.**
|
|
18
18
|
|
|
19
|
-
Present the ranked candidates, the AI reasoning, and the recommended pick. Wait for explicit confirmation before
|
|
19
|
+
Present the ranked candidates, the AI reasoning, and the recommended pick. Wait for explicit confirmation before transitioning. The `assignee` field means _who is executing_ and is claimed at execution start by harness-execution — picking an item must NOT mark it assigned (an early assignee makes the item look human-claimed and the orchestrator silently skips it).
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
@@ -133,28 +133,27 @@ Ask the human in plain text (matching the `y/n/pick another` example above). Do
|
|
|
133
133
|
- If **pick another**: ask which candidate number, then proceed with that pick.
|
|
134
134
|
- If **no**: stop. No changes made.
|
|
135
135
|
|
|
136
|
-
### Phase 4:
|
|
136
|
+
### Phase 4: TRANSITION -- Hand Off to the Next Skill
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
**Do NOT write the `assignee` field here.** Selection picks the item; it does not
|
|
139
|
+
claim it. harness-execution claims the item (`status=in-progress` + `assignee`) at
|
|
140
|
+
execution start. Writing an assignee at selection makes the orchestrator treat the
|
|
141
|
+
item as already-claimed and silently skip it (the bug this skill must not reintroduce).
|
|
142
|
+
The item stays `planned`/`backlog` with `Assignee: —` and remains orchestrator-eligible.
|
|
139
143
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
- This updates the feature's `Assignee` field with assignment history tracking
|
|
150
|
-
- Automatically triggers external sync (GitHub Issues) if tracker config exists in `harness.config.json`
|
|
151
|
-
- External sync is fire-and-forget — errors are logged but do not block the assignment
|
|
144
|
+
**Sharded mode + auto-done.** When the claim is later written (at execution start),
|
|
145
|
+
in sharded mode (`docs/roadmap.d/` present) it patches the **single row's shard**
|
|
146
|
+
and appends an assignment record to the shared `_meta.md`, then regenerates the
|
|
147
|
+
`docs/roadmap.md` aggregate — stage both. And there is **no manual done-marking
|
|
148
|
+
step**: a row reaches `done` automatically when the implementing PR merges
|
|
149
|
+
(merge-triggered auto-done via `External-ID`; the reconciler clears the assignee per
|
|
150
|
+
RMH005). See knowledge [`merge-triggered-auto-done.md`](../../../../docs/knowledge/roadmap/merge-triggered-auto-done.md).
|
|
152
151
|
|
|
153
|
-
|
|
152
|
+
1. Determine the transition target:
|
|
154
153
|
- If the feature has a `spec` field (non-null): transition to `harness:autopilot`
|
|
155
154
|
- If the feature has no `spec`: transition to `harness:brainstorming`
|
|
156
155
|
|
|
157
|
-
|
|
156
|
+
2. Present the transition to the human via `emit_interaction`:
|
|
158
157
|
|
|
159
158
|
```json
|
|
160
159
|
emit_interaction({
|
|
@@ -163,16 +162,16 @@ Ask the human in plain text (matching the `y/n/pick another` example above). Do
|
|
|
163
162
|
transition: {
|
|
164
163
|
completedPhase: "roadmap-pilot",
|
|
165
164
|
suggestedNext: "<brainstorming|autopilot>",
|
|
166
|
-
reason: "Feature '<name>'
|
|
165
|
+
reason: "Feature '<name>' selected and ready for <brainstorming|execution>",
|
|
167
166
|
artifacts: ["docs/roadmap.md"],
|
|
168
167
|
requiresConfirmation: true,
|
|
169
|
-
summary: "
|
|
168
|
+
summary: "Selected '<name>'. <Spec exists -- ready for autopilot|No spec -- needs brainstorming first>. (Not assigned — harness-execution claims it at execution start.)",
|
|
170
169
|
qualityGate: {
|
|
171
170
|
checks: [
|
|
172
171
|
{ "name": "roadmap-parsed", "passed": true },
|
|
173
172
|
{ "name": "candidate-scored", "passed": true },
|
|
174
173
|
{ "name": "human-confirmed", "passed": true },
|
|
175
|
-
{ "name": "assignment-
|
|
174
|
+
{ "name": "no-assignment-at-selection", "passed": true }
|
|
176
175
|
],
|
|
177
176
|
allPassed: true
|
|
178
177
|
}
|
|
@@ -180,7 +179,7 @@ Ask the human in plain text (matching the `y/n/pick another` example above). Do
|
|
|
180
179
|
})
|
|
181
180
|
```
|
|
182
181
|
|
|
183
|
-
|
|
182
|
+
3. Run `harness validate`.
|
|
184
183
|
|
|
185
184
|
---
|
|
186
185
|
|
|
@@ -190,19 +189,18 @@ Ask the human in plain text (matching the `y/n/pick another` example above). Do
|
|
|
190
189
|
- **`loadProjectRoadmapMode` / `loadTrackerClientConfigFromProject` / `createTrackerClient`** -- Resolve `roadmap.mode` and obtain a `RoadmapTrackerClient` for file-less mode. Import from `@harness-engineering/core`.
|
|
191
190
|
- **`scoreRoadmapCandidatesForMode`** -- Mode-aware scoring entry point. Import from `@harness-engineering/core`. In file-backed mode delegates to `scoreRoadmapCandidates`; in file-less mode routes through `scoreRoadmapCandidatesFileLess` (priority + createdAt sort, FR-S3).
|
|
192
191
|
- **`scoreRoadmapCandidates`** -- Underlying file-backed scoring algorithm. Prefer `scoreRoadmapCandidatesForMode` from the skill; direct callers in file-backed-only code paths can still use this.
|
|
193
|
-
- **`
|
|
194
|
-
- **`emit_interaction`** -- Used for the skill transition at the end. Transitions to `harness:brainstorming` (no spec) or `harness:autopilot` (spec exists).
|
|
192
|
+
- **`emit_interaction`** -- Used for the skill transition at the end. Transitions to `harness:brainstorming` (no spec) or `harness:autopilot` (spec exists). This skill does NOT call `manage_roadmap update` to assign — the `assignee` field is owned by harness-execution (claim at execution start), enforced by RMH005 (`assignee ≠ null ⟺ in-progress`).
|
|
195
193
|
- **`STRATEGY.md` alignment (Phase 2 step 1a)** -- When present at repo root and valid, loaded via `validateStrategy` + `parseStrategyDoc` + `asStrategyDoc` from `@harness-engineering/core`. Applied as a bounded tiebreaker bonus (max `+0.75`) only when candidates score within `0.05` on the base formula. Boundary: roadmap-pilot READS; `harness-strategy` WRITES. Never modify `STRATEGY.md` from this skill.
|
|
196
|
-
- **`harness validate`** -- Run after
|
|
194
|
+
- **`harness validate`** -- Run after the transition is presented.
|
|
197
195
|
|
|
198
196
|
## Success Criteria
|
|
199
197
|
|
|
200
198
|
1. Roadmap is parsed and unblocked planned/backlog items are scored
|
|
201
199
|
2. Scoring uses two-tier sort: explicit priority first, then weighted score
|
|
202
200
|
3. AI reads top candidates' specs and provides recommendation with reasoning
|
|
203
|
-
4. Human confirms before
|
|
204
|
-
5.
|
|
205
|
-
6.
|
|
201
|
+
4. Human confirms before the transition is made
|
|
202
|
+
5. Selection does NOT write the `assignee` field (no assignment, no history record, no external assignee sync) — the pick stays `planned`/`backlog` and orchestrator-eligible
|
|
203
|
+
6. The `assignee` field is owned by harness-execution, which claims at execution start; RMH005 enforces `assignee ≠ null ⟺ in-progress`
|
|
206
204
|
7. Transition routes to brainstorming (no spec) or autopilot (spec exists)
|
|
207
205
|
8. When a pulse report exists, the recommendation rationale cites pulse signal for any top-3 candidate whose area is referenced in the pulse Headlines or Followups.
|
|
208
206
|
9. When `STRATEGY.md` is present and valid AND two candidates score within `0.05` on the base formula, the recommendation rationale cites strategy-alignment as the tiebreaker. The bonus never overrides a meaningful base-score difference.
|
|
@@ -211,12 +209,13 @@ Ask the human in plain text (matching the `y/n/pick another` example above). Do
|
|
|
211
209
|
|
|
212
210
|
## Rationalizations to Reject
|
|
213
211
|
|
|
214
|
-
| Rationalization | Reality
|
|
215
|
-
| ----------------------------------------------------------------------------------------------------------------------- |
|
|
216
|
-
| "The top-scored candidate is obviously correct, so I can
|
|
217
|
-
| "
|
|
218
|
-
| "
|
|
219
|
-
| "
|
|
212
|
+
| Rationalization | Reality |
|
|
213
|
+
| ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
214
|
+
| "The top-scored candidate is obviously correct, so I can transition without asking the human" | The Iron Law: never transition without the human confirming the recommendation first. |
|
|
215
|
+
| "I'll write the assignee now so the pick is recorded / the user is credited" | Selection never writes `assignee`. An assignee means _in-progress_ (set by harness-execution at execution start). Writing it at selection makes the orchestrator silently skip the item — the exact bug this skill must not reintroduce. |
|
|
216
|
+
| "Affinity data is not available so the scoring is degraded -- I should just pick the first planned item" | Proceed without affinity scoring by zeroing out the affinity weight. Position and dependents signals still produce meaningful rankings. |
|
|
217
|
+
| "The feature has no spec, but I can skip brainstorming and jump straight to planning since the summary is clear enough" | No spec routes to brainstorming, spec exists routes to autopilot. A one-line roadmap summary is not a spec. |
|
|
218
|
+
| "STRATEGY.md exists, so I should let it override the top-scored candidate when alignment is clear" | The alignment bonus is bounded (max `+0.75`) and only fires when base scores are within `0.05`. It is a tiebreaker, not a hard filter — a clearly higher-scored item still wins. |
|
|
220
219
|
|
|
221
220
|
## Examples
|
|
222
221
|
|
|
@@ -252,25 +251,23 @@ Proceed? (y/n/pick another)
|
|
|
252
251
|
|
|
253
252
|
Human confirms **y**.
|
|
254
253
|
|
|
255
|
-
**Phase 4:
|
|
254
|
+
**Phase 4: TRANSITION**
|
|
256
255
|
|
|
257
256
|
```
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
Roadmap updated: docs/roadmap.md
|
|
261
|
-
External sync: github:harness-eng/harness#43 assigned (automatic)
|
|
257
|
+
Graph Connector stays planned, Assignee: — (not assigned at selection).
|
|
258
|
+
harness-execution will claim it (status=in-progress + assignee) at execution start.
|
|
262
259
|
|
|
263
260
|
Transitioning to harness:autopilot (spec exists)...
|
|
264
261
|
```
|
|
265
262
|
|
|
266
263
|
## Gates
|
|
267
264
|
|
|
268
|
-
- **No
|
|
269
|
-
- **No
|
|
265
|
+
- **No transition without human confirmation.** The CONFIRM phase must complete with explicit approval before transitioning.
|
|
266
|
+
- **No assignment at selection.** This skill never writes the `assignee` field — that field means _who is executing_ and is claimed at execution start by harness-execution. Writing it here would make the orchestrator silently skip the item.
|
|
270
267
|
- **No scoring without a parsed roadmap.** If `docs/roadmap.md` does not exist or fails to parse, stop with an error.
|
|
271
268
|
|
|
272
269
|
## Escalation
|
|
273
270
|
|
|
274
271
|
- **When no unblocked candidates exist:** Inform the human. Suggest reviewing blocked items to see if blockers can be resolved, or adding new features via `harness-roadmap --add`.
|
|
275
272
|
- **When affinity data is unavailable:** Proceed without affinity scoring (weight falls to 0 for all candidates). Note this in the output.
|
|
276
|
-
- **When
|
|
273
|
+
- **When the human asks you to assign the item to them at selection:** Explain that the `assignee` field means _who is executing_ and is claimed at execution start by harness-execution; assigning at selection makes the orchestrator silently skip the item (enforced by RMH005). Proceed with the transition instead.
|
|
@@ -174,19 +174,16 @@ Use severity markers for critical findings: `**[CRITICAL]**` for blocking issues
|
|
|
174
174
|
|
|
175
175
|
### Verification Sign-Off
|
|
176
176
|
|
|
177
|
-
After producing the report, request acceptance:
|
|
177
|
+
After producing the report, request acceptance in plain text. Ask 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). Present it as:
|
|
178
178
|
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
risk: "<low if PASS, high if gaps remain>"
|
|
188
|
-
}
|
|
189
|
-
})
|
|
179
|
+
```markdown
|
|
180
|
+
Verification report: <VERDICT>. Accept and proceed?
|
|
181
|
+
|
|
182
|
+
Context: <N artifacts checked, N gaps found>
|
|
183
|
+
Impact: Accepting proceeds to code review. Declining requires gap resolution.
|
|
184
|
+
Risk: <low if PASS, high if gaps remain>
|
|
185
|
+
|
|
186
|
+
Proceed? (yes/no)
|
|
190
187
|
```
|
|
191
188
|
|
|
192
189
|
### Handoff and Transition
|