@harness-engineering/cli 2.7.0 → 2.8.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/adversarial-reviewer.yaml +43 -0
- package/dist/agents/personas/frontend-races-reviewer.yaml +54 -0
- package/dist/agents/personas/typescript-strict-reviewer.yaml +53 -0
- package/dist/agents/skills/CHANGELOG.md +12 -0
- package/dist/agents/skills/claude-code/align-design-system/SKILL.md +18 -0
- package/dist/agents/skills/claude-code/align-design-system/skill.yaml +3 -0
- package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +37 -5
- package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +107 -22
- package/dist/agents/skills/claude-code/harness-code-review/references/confidence-rubric.md +45 -0
- package/dist/agents/skills/claude-code/harness-code-review/references/risk-keywords.md +40 -0
- package/dist/agents/skills/claude-code/harness-code-review/skill.yaml +3 -0
- package/dist/agents/skills/claude-code/harness-compound/SKILL.md +7 -4
- package/dist/agents/skills/claude-code/harness-ideate/SKILL.md +277 -0
- package/dist/agents/skills/claude-code/harness-ideate/references/scoring.md +88 -0
- package/dist/agents/skills/claude-code/harness-ideate/skill.yaml +66 -0
- package/dist/agents/skills/claude-code/harness-planning/SKILL.md +14 -4
- package/dist/agents/skills/claude-code/harness-pulse/SKILL.md +12 -16
- package/dist/agents/skills/claude-code/harness-roadmap-pilot/SKILL.md +34 -6
- package/dist/agents/skills/claude-code/harness-strategy/SKILL.md +152 -0
- package/dist/agents/skills/claude-code/harness-strategy/references/interview.md +122 -0
- package/dist/agents/skills/claude-code/harness-strategy/skill.yaml +54 -0
- package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +76 -10
- package/dist/agents/skills/claude-code/naming-craft/SKILL.md +74 -2
- package/dist/agents/skills/codex/align-design-system/SKILL.md +18 -0
- package/dist/agents/skills/codex/align-design-system/skill.yaml +3 -0
- package/dist/agents/skills/codex/harness-brainstorming/SKILL.md +37 -5
- package/dist/agents/skills/codex/harness-code-review/SKILL.md +107 -22
- package/dist/agents/skills/codex/harness-code-review/references/confidence-rubric.md +45 -0
- package/dist/agents/skills/codex/harness-code-review/references/risk-keywords.md +40 -0
- package/dist/agents/skills/codex/harness-code-review/skill.yaml +3 -0
- package/dist/agents/skills/codex/harness-compound/SKILL.md +7 -4
- package/dist/agents/skills/codex/harness-ideate/SKILL.md +277 -0
- package/dist/agents/skills/codex/harness-ideate/references/scoring.md +88 -0
- package/dist/agents/skills/codex/harness-ideate/skill.yaml +66 -0
- package/dist/agents/skills/codex/harness-planning/SKILL.md +14 -4
- package/dist/agents/skills/codex/harness-pulse/SKILL.md +12 -16
- package/dist/agents/skills/codex/harness-roadmap-pilot/SKILL.md +34 -6
- package/dist/agents/skills/codex/harness-strategy/SKILL.md +152 -0
- package/dist/agents/skills/codex/harness-strategy/references/interview.md +122 -0
- package/dist/agents/skills/codex/harness-strategy/skill.yaml +54 -0
- package/dist/agents/skills/codex/initialize-harness-project/SKILL.md +76 -10
- package/dist/agents/skills/codex/naming-craft/SKILL.md +74 -2
- package/dist/agents/skills/cursor/align-design-system/SKILL.md +18 -0
- package/dist/agents/skills/cursor/align-design-system/skill.yaml +3 -0
- package/dist/agents/skills/cursor/harness-brainstorming/SKILL.md +37 -5
- package/dist/agents/skills/cursor/harness-code-review/SKILL.md +107 -22
- package/dist/agents/skills/cursor/harness-code-review/references/confidence-rubric.md +45 -0
- package/dist/agents/skills/cursor/harness-code-review/references/risk-keywords.md +40 -0
- package/dist/agents/skills/cursor/harness-code-review/skill.yaml +3 -0
- package/dist/agents/skills/cursor/harness-compound/SKILL.md +7 -4
- package/dist/agents/skills/cursor/harness-ideate/SKILL.md +277 -0
- package/dist/agents/skills/cursor/harness-ideate/references/scoring.md +88 -0
- package/dist/agents/skills/cursor/harness-ideate/skill.yaml +66 -0
- package/dist/agents/skills/cursor/harness-planning/SKILL.md +14 -4
- package/dist/agents/skills/cursor/harness-pulse/SKILL.md +12 -16
- package/dist/agents/skills/cursor/harness-roadmap-pilot/SKILL.md +34 -6
- package/dist/agents/skills/cursor/harness-strategy/SKILL.md +152 -0
- package/dist/agents/skills/cursor/harness-strategy/references/interview.md +122 -0
- package/dist/agents/skills/cursor/harness-strategy/skill.yaml +54 -0
- package/dist/agents/skills/cursor/initialize-harness-project/SKILL.md +76 -10
- package/dist/agents/skills/cursor/naming-craft/SKILL.md +74 -2
- package/dist/agents/skills/gemini-cli/align-design-system/SKILL.md +18 -0
- package/dist/agents/skills/gemini-cli/align-design-system/skill.yaml +3 -0
- package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +37 -5
- package/dist/agents/skills/gemini-cli/harness-code-review/SKILL.md +107 -22
- package/dist/agents/skills/gemini-cli/harness-code-review/references/confidence-rubric.md +45 -0
- package/dist/agents/skills/gemini-cli/harness-code-review/references/risk-keywords.md +40 -0
- package/dist/agents/skills/gemini-cli/harness-code-review/skill.yaml +3 -0
- package/dist/agents/skills/gemini-cli/harness-compound/SKILL.md +7 -4
- package/dist/agents/skills/gemini-cli/harness-ideate/SKILL.md +277 -0
- package/dist/agents/skills/gemini-cli/harness-ideate/references/scoring.md +88 -0
- package/dist/agents/skills/gemini-cli/harness-ideate/skill.yaml +66 -0
- package/dist/agents/skills/gemini-cli/harness-planning/SKILL.md +14 -4
- package/dist/agents/skills/gemini-cli/harness-pulse/SKILL.md +12 -16
- package/dist/agents/skills/gemini-cli/harness-roadmap-pilot/SKILL.md +34 -6
- package/dist/agents/skills/gemini-cli/harness-strategy/SKILL.md +152 -0
- package/dist/agents/skills/gemini-cli/harness-strategy/references/interview.md +122 -0
- package/dist/agents/skills/gemini-cli/harness-strategy/skill.yaml +54 -0
- package/dist/agents/skills/gemini-cli/initialize-harness-project/SKILL.md +76 -10
- package/dist/agents/skills/gemini-cli/naming-craft/SKILL.md +74 -2
- package/dist/agents/skills/package.json +1 -1
- package/dist/agents/skills/tests/harness-strategy.test.ts +145 -0
- package/dist/agents-md-WMJO5HSM.js +13 -0
- package/dist/analyzer-V633GUHY-MBCQWKDU.js +26 -0
- package/dist/{architecture-ZTEHGIHD.js → architecture-EVYVGPRZ.js} +6 -6
- package/dist/{assess-project-OKDW3YSK.js → assess-project-KZG563SO.js} +1 -1
- package/dist/bin/harness-mcp.js +17 -17
- package/dist/bin/harness.js +27 -27
- package/dist/{check-phase-gate-YJWFDW66.js → check-phase-gate-MK364VXS.js} +6 -6
- package/dist/{chunk-6UHDQP2N.js → chunk-2N4OENGE.js} +1 -1
- package/dist/{chunk-OLTVDPA2.js → chunk-2SNRCAC3.js} +3 -3
- package/dist/{chunk-HLPY3RHE.js → chunk-4BDOSCNY.js} +909 -559
- package/dist/{chunk-S7GEONXL.js → chunk-5XL5QJ5B.js} +2 -2
- package/dist/{chunk-OQE6ME2Z.js → chunk-7EQAZKJ5.js} +2 -2
- package/dist/{chunk-QUPC37UB.js → chunk-ACOOG3UW.js} +6 -6
- package/dist/{chunk-B4OLYXZ4.js → chunk-B7KMTHN3.js} +89 -7
- package/dist/{chunk-OH3NXXUY.js → chunk-BDGTZRZ6.js} +11 -1
- package/dist/{chunk-P7EO7USC.js → chunk-C7J55C6E.js} +10 -10
- package/dist/{chunk-4EGPFB7V.js → chunk-CAQPSFPT.js} +4753 -744
- package/dist/{chunk-TIH53QXY.js → chunk-CLI4K2CH.js} +1 -1
- package/dist/{chunk-ZKA3TGYS.js → chunk-EEFRPEWT.js} +1 -1
- package/dist/{chunk-TIZ3L6CU.js → chunk-FZ5MBXEG.js} +6 -6
- package/dist/{chunk-IY2TZLY5.js → chunk-GOHWCHCS.js} +1809 -812
- package/dist/{chunk-VG6UK6G6.js → chunk-HRSE6IQD.js} +2 -2
- package/dist/{chunk-67RP7MLR.js → chunk-KBCPELBC.js} +3 -3
- package/dist/{chunk-MQG7FHXX.js → chunk-KI6PHH6Q.js} +3 -3
- package/dist/{chunk-HMMSWRWR.js → chunk-LADPYELQ.js} +23 -3
- package/dist/{chunk-W3PDVZ4I.js → chunk-N55WOGN3.js} +90 -21
- package/dist/{chunk-H2ZJOJ7A.js → chunk-PP6ZRL5T.js} +316 -42
- package/dist/{chunk-B3B64OPD.js → chunk-STESM73J.js} +2 -2
- package/dist/{chunk-WOXR6I3R.js → chunk-UBZQE3JN.js} +2 -2
- package/dist/{chunk-6T5AYG5S.js → chunk-UJFNIWC7.js} +5 -5
- package/dist/{chunk-CXAHK5PJ.js → chunk-UUO4K7NX.js} +9 -9
- package/dist/{chunk-Z2GUITAS.js → chunk-UXPWSV3B.js} +9 -9
- package/dist/{chunk-PARV3G2F.js → chunk-VBNJAKUH.js} +2 -2
- package/dist/{chunk-XTIPZUPR.js → chunk-X4EFYVCZ.js} +2 -2
- package/dist/{ci-workflow-YGTQTNVC.js → ci-workflow-IW2H5DC4.js} +5 -5
- package/dist/{dist-E3SAAHCM.js → dist-ICW4QUEW.js} +5 -1
- package/dist/{dist-XIJWWQ5N.js → dist-JCFK263L.js} +52 -4
- package/dist/{dist-R3TOOPJ7.js → dist-OWHMNL4W.js} +1 -1
- package/dist/{docs-KCTLXK2G.js → docs-7CP6VV42.js} +6 -6
- package/dist/engine-MKJEBWU7.js +13 -0
- package/dist/{entropy-M27JUL3V.js → entropy-6JOZJYG7.js} +5 -5
- package/dist/{feedback-W25QO3OL.js → feedback-T65AEJEG.js} +1 -1
- package/dist/{generate-agent-definitions-RNMU5U5R.js → generate-agent-definitions-4VI4YTO2.js} +6 -6
- package/dist/{glob-helper-EX4YZKZO.js → glob-helper-GLZAURJC.js} +1 -1
- package/dist/{graph-loader-EIFEOUVI.js → graph-loader-HHXN5FLP.js} +1 -1
- package/dist/index.d.ts +627 -6
- package/dist/index.js +27 -27
- package/dist/{loader-HZKJ5ABV.js → loader-AWTHHE3A.js} +5 -5
- package/dist/{mcp-NEAPIDTT.js → mcp-JBIBINO2.js} +17 -17
- package/dist/{performance-3AVQUDRG.js → performance-NCOUDOMW.js} +6 -6
- package/dist/{review-pipeline-KA7SGUXJ.js → review-pipeline-YIC6JPMY.js} +5 -5
- package/dist/{runtime-IP6FVV5M.js → runtime-5MHV4UEE.js} +5 -5
- package/dist/{scan-LYKLM4EQ.js → scan-P7YFKB77.js} +1 -1
- package/dist/{security-EAR4FJWI.js → security-VZPJNIDP.js} +1 -1
- package/dist/{validate-EVH3UXIC.js → validate-7BE4VTFI.js} +6 -6
- package/dist/validate-cross-check-F7GEBRDH.js +13 -0
- package/package.json +7 -7
- package/dist/agents-md-267R2NUJ.js +0 -13
- package/dist/analyzer-VY6DJVOU-WYKV3TTW.js +0 -26
- package/dist/engine-J64WPH5K.js +0 -13
- package/dist/validate-cross-check-SNE3SQOB.js +0 -13
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# Harness Ideate
|
|
2
|
+
|
|
3
|
+
> Pre-brainstorm ideation. Generates candidate ideas, critiques each against its strongest objection, and ranks them by `(impact × confidence) ÷ effort`. Writes a single ranked artifact to `docs/ideation/<slug>-YYYY-MM-DD.md`. **Produces ranked ideation, not specs** — brainstorming consumes the output.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
- Before brainstorming, when the feature to design has not yet been selected
|
|
8
|
+
- When the user asks "what should we build next in area X?" and there are several plausible answers
|
|
9
|
+
- When a single domain (auth, pulse reports, onboarding…) has 5–10 candidate ideas worth comparing
|
|
10
|
+
- After updating `STRATEGY.md` and wanting to surface candidates aligned with the new tracks
|
|
11
|
+
- NOT when the feature is already selected — go straight to `harness-brainstorming`
|
|
12
|
+
- NOT for ranking existing roadmap items — that is `harness-roadmap-pilot`'s job
|
|
13
|
+
- NOT for generating specs, plans, or code — this skill writes one ideation artifact and stops
|
|
14
|
+
- NOT for refreshing `STRATEGY.md` — that is `harness-strategy`'s job
|
|
15
|
+
|
|
16
|
+
## Process
|
|
17
|
+
|
|
18
|
+
### Iron Law
|
|
19
|
+
|
|
20
|
+
**The skill produces exactly ONE ranked artifact per run, at `docs/ideation/<slug>-YYYY-MM-DD.md`, and NEVER produces a spec, plan, ADR, or code.** If the user wants a spec from a ranked idea, they invoke `harness-brainstorming` next — that is the contract.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
### Phase 1: GROUND — Read STRATEGY.md and Confirm the Topic
|
|
25
|
+
|
|
26
|
+
1. **Resolve the focus argument.** If the user passed `--focus` (or supplied a one-line topic in the conversation), use it verbatim. Otherwise ask:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
What is the ideation topic? One short line (e.g., "onboarding for plugin-only users",
|
|
30
|
+
"lateral review depth", "pulse-report follow-up routing").
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Capture the answer; do not proceed without one.
|
|
34
|
+
|
|
35
|
+
2. **Resolve the count.** Default to 10 if `--count` is unset. Clamp silently to `[5, 25]` (`<5` is too few to rank meaningfully; `>25` loses signal). Proceed with the clamped value.
|
|
36
|
+
|
|
37
|
+
3. **Read `STRATEGY.md` (grounding).** Call `read_strategy({ path: process.cwd() })` on the harness MCP server — it returns `{ present, valid, doc?, error? }` and runs validation + parsing inside the server so the project does not need `@harness-engineering/core` installed.
|
|
38
|
+
|
|
39
|
+
Three cases:
|
|
40
|
+
- **`{ present: false }`:** print one line — `STRATEGY.md not present — ranking will use impact × confidence ÷ effort only; no strategy-alignment tiebreaker`. Continue.
|
|
41
|
+
- **`{ present: true, valid: true, doc }`:** capture `doc.sections` for `Target problem`, `Our approach`, `Who it's for`, and `Tracks`. These four sections drive the strategy-alignment tiebreaker in Phase 4.
|
|
42
|
+
- **`{ present: true, valid: false, error }`:** print `error` verbatim and continue without strategy grounding. Do NOT block; this skill is not the place to repair `STRATEGY.md`. Suggest `/harness:strategy` as a follow-up.
|
|
43
|
+
|
|
44
|
+
Fallback for environments without the MCP server: `node -e "import('@harness-engineering/core').then(m => m.validateStrategy(process.cwd()).then(r => console.log(JSON.stringify(r))))"` — only works when `@harness-engineering/core` is resolvable from the project's `node_modules`.
|
|
45
|
+
|
|
46
|
+
4. **Confirm the topic.** Before generating, surface a 2-line summary:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
Topic: <focus>
|
|
50
|
+
Count: <N>
|
|
51
|
+
Strategy grounding: <enabled|disabled — reason>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Ask: `Proceed with these inputs? (y/n)`. Wait for confirmation.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
### Phase 2: GENERATE — Produce Candidate Ideas
|
|
59
|
+
|
|
60
|
+
Generate exactly N candidate ideas. Each idea is a structured object with the following fields:
|
|
61
|
+
|
|
62
|
+
| Field | Type | Description |
|
|
63
|
+
| ------------ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
64
|
+
| `premise` | string (1 sentence) | What this idea is, in one declarative sentence. Not aspirational — what the change IS, not what we hope it achieves. |
|
|
65
|
+
| `persona` | string (1 sentence) | Target persona segment (specific, not "developers"). If STRATEGY.md is present, prefer phrasing from its `Who it's for`. |
|
|
66
|
+
| `complexity` | `low \| medium \| high` | Rough engineering complexity estimate. |
|
|
67
|
+
| `key_risk` | string (1 sentence) | The single biggest reason this idea might fail or not be worth doing. Used in Phase 3 as the seed for critique. |
|
|
68
|
+
| `impact` | `low \| medium \| high` | How much this matters if it works. Mapped to `1/2/3` for ranking. |
|
|
69
|
+
| `confidence` | `low \| medium \| high` | How confident we are that we can pull it off. Mapped to `1/2/3` for ranking. |
|
|
70
|
+
| `effort` | `low \| medium \| high` | Engineering effort to deliver. Mapped to `1/2/3` for ranking. |
|
|
71
|
+
|
|
72
|
+
**Generation rules:**
|
|
73
|
+
|
|
74
|
+
- **Spread the complexity surface.** Aim for at least one `low` and one `high` complexity idea; resist clustering everything as `medium`.
|
|
75
|
+
- **Resist near-duplicates.** Two ideas with the same `premise` are one idea. If two ideas only differ by a parameter ("X for web" vs "X for mobile"), collapse them into a single idea with a parametric premise.
|
|
76
|
+
- **Be honest about effort.** A `low`-effort idea must be plausibly implementable in <1 sprint by one engineer. If you find yourself defaulting everything to `medium`, slow down and re-estimate one extreme.
|
|
77
|
+
- **When STRATEGY.md is present**, at least 60% of ideas should plausibly serve a current track in `Tracks`. Stretch ideas outside the tracks are allowed and useful, but the majority anchors in.
|
|
78
|
+
|
|
79
|
+
Present the N candidates as a numbered list. Each line is 2-3 sentences max:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
1. [Premise]. Persona: [...]. Complexity: medium. Key risk: [...]. Impact/Confidence/Effort: M/M/L.
|
|
83
|
+
2. [Premise]. Persona: [...]. Complexity: low. Key risk: [...]. Impact/Confidence/Effort: H/L/L.
|
|
84
|
+
...
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
### Phase 3: CRITIQUE — Identify and Address Strongest Objections
|
|
90
|
+
|
|
91
|
+
For each candidate, surface the **single strongest objection** — the best argument against doing this idea. The seed is `key_risk` from Phase 2, but the critique should sharpen it (one paragraph, not one sentence):
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
Idea 3: [Premise].
|
|
95
|
+
Strongest objection: [...]. Most likely failure mode: [...]. What would need to be true
|
|
96
|
+
for this objection to NOT hold: [...].
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
After all N critiques are presented, ask the user:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
Which objections do you want to answer (vs. accept as a downside)?
|
|
103
|
+
Options:
|
|
104
|
+
- all — I'll address every objection
|
|
105
|
+
- none — accept all critiques as known downsides
|
|
106
|
+
- <list of numbers, e.g., "1, 3, 7">
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
For each idea the user elects to answer, ask: `For idea N, what makes the objection wrong or addressable?` Capture the user's one-paragraph answer. If the user cannot answer convincingly, leave the objection standing (this is a signal — it lowers the idea's ranking).
|
|
110
|
+
|
|
111
|
+
Critique answers do NOT change the impact/confidence/effort scores from Phase 2. They feed into the rationale shown alongside each ranked idea in Phase 5.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
### Phase 4: RANK — Score and Order
|
|
116
|
+
|
|
117
|
+
For each candidate, compute `base_score = (impact × confidence) ÷ effort` using the `low|medium|high → 1|2|3` mapping documented in `references/scoring.md`. Higher is better; range is `[≈0.33, 9.0]`.
|
|
118
|
+
|
|
119
|
+
**Strategy-alignment tiebreaker.** When `STRATEGY.md` was grounded in Phase 1, compute an alignment bonus per candidate:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
alignment_bonus =
|
|
123
|
+
(premise plausibly advances a Tracks bullet ? 0.5 : 0)
|
|
124
|
+
+ (premise/persona references Target problem or Our approach ? 0.25 : 0)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Maximum bonus `+0.75`. The bonus is **bounded**: it is applied only when the absolute difference between two adjacent candidates' base scores is `≤ 0.05`. Outside that tie window, the base score wins and the bonus is recorded for transparency but does NOT change rank order. See `references/scoring.md` for the full contract (including the worked example and the boundary with `harness-roadmap-pilot`'s identical tiebreaker shape).
|
|
128
|
+
|
|
129
|
+
Sort by final score descending. Stable on ties (preserve generation order so the user can find the original list).
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
### Phase 5: WRITE — Persist the Ranked Artifact
|
|
134
|
+
|
|
135
|
+
1. **Compute the slug.** Kebab-case the focus argument; lowercase; collapse whitespace and `[^a-z0-9-]` into `-`; trim leading/trailing `-`; truncate to **≤30 characters**. Example: `"onboarding for plugin-only users"` → `onboarding-for-plugin-only-use`.
|
|
136
|
+
|
|
137
|
+
2. **Compute today's date** as `YYYY-MM-DD` (UTC).
|
|
138
|
+
|
|
139
|
+
3. **Compute the output path.** `docs/ideation/<slug>-<YYYY-MM-DD>.md`. If that path already exists (same focus, same day), append a 6-character lowercase hex suffix derived from `sha1(focus + iso_timestamp).slice(0, 6)`:
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
docs/ideation/onboarding-for-plugin-only-use-2026-06-02.md # first run
|
|
143
|
+
docs/ideation/onboarding-for-plugin-only-use-2026-06-02-a3f9b2.md # collision
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
4. **Render the artifact.** Frontmatter + ranked list. See ranking math in `references/scoring.md`. Required fields:
|
|
147
|
+
|
|
148
|
+
```markdown
|
|
149
|
+
---
|
|
150
|
+
topic: <focus argument verbatim>
|
|
151
|
+
generated_at: <ISO 8601 timestamp>
|
|
152
|
+
strategy_grounded: <true | false>
|
|
153
|
+
strategy_path: <STRATEGY.md path if grounded, else null>
|
|
154
|
+
count_requested: <N>
|
|
155
|
+
count_generated: <N>
|
|
156
|
+
ranking_formula: '(impact × confidence) ÷ effort; strategy-alignment tiebreaker (max +0.75) applied only when |Δbase_score| ≤ 0.05'
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
# Ideation: <focus>
|
|
160
|
+
|
|
161
|
+
## Inputs
|
|
162
|
+
|
|
163
|
+
- Topic: <focus>
|
|
164
|
+
- Generated: <ISO timestamp>
|
|
165
|
+
- Strategy grounding: <enabled | disabled with one-line reason>
|
|
166
|
+
|
|
167
|
+
## Ranked candidates
|
|
168
|
+
|
|
169
|
+
### 1. <premise> — score: <final>
|
|
170
|
+
|
|
171
|
+
- Persona: <...>
|
|
172
|
+
- Complexity: <low|medium|high>
|
|
173
|
+
- Impact / Confidence / Effort: <H/M/L> — base score <X.XX>
|
|
174
|
+
- Strategy alignment: <none | +0.25 persona | +0.5 track:<name>> — final score <Y.YY>
|
|
175
|
+
- Strongest objection: <one paragraph>
|
|
176
|
+
- Objection answered: <yes/no — if yes, one paragraph rebuttal>
|
|
177
|
+
|
|
178
|
+
### 2. ...
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
5. **Write the file.** Create `docs/ideation/` if it does not exist. Write via the standard `Write` tool — no Node one-liner is required here; the content is generated by the skill, not user-supplied prose with shell-escape hazards.
|
|
182
|
+
|
|
183
|
+
6. **Print the handoff.** Three lines:
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
Ideation artifact written: docs/ideation/<slug>-<date>.md
|
|
187
|
+
Top pick: <#1 premise> — score <Y.YY>
|
|
188
|
+
Next: invoke /harness:brainstorming <feature> to take a candidate into a spec, OR /harness:roadmap to enqueue picks for later.
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Harness Integration
|
|
194
|
+
|
|
195
|
+
- **Harness MCP tools consumed by this skill** (canonical execution path — no project-local `@harness-engineering/core` required):
|
|
196
|
+
- `read_strategy({ path })` — Phase 1 grounding oracle. Returns `{ present, valid, doc?, error? }` (the server runs `validateStrategy` + `parseStrategyDoc` + `asStrategyDoc` internally).
|
|
197
|
+
- **`@harness-engineering/core`** (only directly relevant when the MCP server is unavailable):
|
|
198
|
+
- `validateStrategy(cwd)`, `parseStrategyDoc(raw)` + `asStrategyDoc(parsed)`, `StrategyDocSchema`, `REQUIRED_STRATEGY_SECTIONS`.
|
|
199
|
+
- **Boundary with `harness-strategy`** — strategy WRITES `STRATEGY.md`; ideate READS it. Ideate never modifies `STRATEGY.md` and never offers to repair an invalid one (suggest `/harness:strategy` and continue without grounding).
|
|
200
|
+
- **Boundary with `harness-brainstorming`** — ideate produces a ranked artifact at `docs/ideation/`; brainstorming produces a spec at `docs/changes/<feature>/proposal.md`. They have non-overlapping output locations (Decision 5 of the strategic-anchor proposal). Ideate's artifact may be cited as an input in a brainstorming spec; brainstorming's spec is NEVER auto-derived from ideate's artifact.
|
|
201
|
+
- **Boundary with `harness-roadmap-pilot`** — ideate generates fresh candidates; roadmap-pilot prioritizes existing roadmap entries. If a user wants ranking-only over the existing roadmap, that is roadmap-pilot, not ideate.
|
|
202
|
+
|
|
203
|
+
## Success Criteria
|
|
204
|
+
|
|
205
|
+
- Exactly one artifact is written per run, at `docs/ideation/<slug>-<YYYY-MM-DD>.md`. No spec, plan, ADR, or code is produced.
|
|
206
|
+
- The artifact contains exactly the number of candidates the user requested (after clamping to `[5, 25]`).
|
|
207
|
+
- Every candidate has all 7 fields populated (premise, persona, complexity, key_risk, impact, confidence, effort).
|
|
208
|
+
- Each candidate has a strongest-objection paragraph; objections the user elected to answer have a rebuttal paragraph.
|
|
209
|
+
- Ranking is by `(impact × confidence) ÷ effort` with the 1/2/3 mapping. Strategy-alignment bonus is applied only when STRATEGY.md is present AND the absolute base-score delta is ≤ 0.05.
|
|
210
|
+
- When `STRATEGY.md` is absent or invalid, the skill completes without error and the artifact's frontmatter records `strategy_grounded: false`.
|
|
211
|
+
- The output filename collision rule (6-char hex suffix on same-day re-run for the same focus) produces a stable, deterministic suffix from `sha1(focus + iso_timestamp)`.
|
|
212
|
+
- The artifact's frontmatter explicitly states the ranking formula so a future reader can reproduce the order.
|
|
213
|
+
|
|
214
|
+
## Examples
|
|
215
|
+
|
|
216
|
+
### Example: With STRATEGY.md (grounded, 10 candidates)
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
User: /harness:ideate --focus "pulse-report follow-up routing"
|
|
220
|
+
|
|
221
|
+
Phase 1:
|
|
222
|
+
Topic confirmed: "pulse-report follow-up routing"
|
|
223
|
+
Count: 10
|
|
224
|
+
STRATEGY.md detected — grounding enabled.
|
|
225
|
+
Tracks read: ["pulse-reports", "compound-engineering", "feedback-loops"]
|
|
226
|
+
Who-it's-for read: "engineering teams adopting harness"
|
|
227
|
+
|
|
228
|
+
Phase 2 (excerpt):
|
|
229
|
+
1. Auto-assign followups to the on-call rotation. Persona: on-call engineer.
|
|
230
|
+
Complexity: medium. Key risk: rotation data may be stale. I/C/E: H/M/M.
|
|
231
|
+
...
|
|
232
|
+
10. Email-digest weekly pulse for distributed teams. Persona: async-first eng.
|
|
233
|
+
Complexity: low. Key risk: duplicates Slack. I/C/E: M/L/L.
|
|
234
|
+
|
|
235
|
+
Phase 3:
|
|
236
|
+
User selects "answer 1, 4, 7"; provides three one-paragraph rebuttals.
|
|
237
|
+
|
|
238
|
+
Phase 4 (ranking, excerpt):
|
|
239
|
+
- Idea 1 base score: (H=3 × M=2) ÷ M=2 = 3.00
|
|
240
|
+
Idea 7 base score: 2.97 (|Δ| = 0.03 ≤ 0.05 — alignment window applies)
|
|
241
|
+
Idea 1 alignment: track match "pulse-reports" (+0.5) + persona match (+0.25) = +0.75 → final 3.75
|
|
242
|
+
Idea 7 alignment: track match "feedback-loops" (+0.5) → final 3.47
|
|
243
|
+
Idea 4 base score: 2.50 (|Δ vs idea 1| = 0.50 > 0.05 — alignment recorded but not applied)
|
|
244
|
+
|
|
245
|
+
Phase 5:
|
|
246
|
+
Write docs/ideation/pulse-report-follow-up-routin-2026-06-02.md
|
|
247
|
+
Top pick: "Auto-assign followups to the on-call rotation" — score 3.50
|
|
248
|
+
Next: invoke /harness:brainstorming "Pulse Followup Routing" to take this into a spec.
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Example: Without STRATEGY.md (no grounding, 5 candidates)
|
|
252
|
+
|
|
253
|
+
- Phase 1: `read_strategy` returns `{ present: false }`. Strategy grounding disabled; skill prints the one-line note and continues.
|
|
254
|
+
- Phase 2: 5 candidates generated. No track-alignment guidance applies; coverage of complexity surface remains a rule.
|
|
255
|
+
- Phase 4: ranking uses `(impact × confidence) ÷ effort` only. No tiebreaker bonus is added.
|
|
256
|
+
- Phase 5: artifact frontmatter has `strategy_grounded: false` and `strategy_path: null`. Handoff still routes the user to brainstorming.
|
|
257
|
+
|
|
258
|
+
### Example: Slug collision (same focus, same day)
|
|
259
|
+
|
|
260
|
+
- Run 1: writes `docs/ideation/onboarding-for-plugin-only-use-2026-06-02.md`.
|
|
261
|
+
- Run 2 (same `--focus`, same day): destination collides. Skill computes `sha1("onboarding for plugin-only users" + "2026-06-02T15:21:04Z").slice(0,6)` → `a3f9b2`. Writes `docs/ideation/onboarding-for-plugin-only-use-2026-06-02-a3f9b2.md`. Both files coexist.
|
|
262
|
+
|
|
263
|
+
## Gates
|
|
264
|
+
|
|
265
|
+
- **One artifact per run, exactly.** A second write on the same run violates the Iron Law.
|
|
266
|
+
- **Never modify `STRATEGY.md`.** Even on present-but-invalid: surface the error and continue without grounding. Repair is `/harness:strategy`'s job.
|
|
267
|
+
- **Never derive a spec from ideate's artifact automatically.** Brainstorming is human-confirmed; ideate's output is an INPUT to brainstorming, not a replacement.
|
|
268
|
+
- **Never produce 0 ideas.** Clamping enforces `N ≥ 5`. If the model would generate near-duplicates to reach N, prefer fewer-but-distinct over more-but-redundant — re-prompt within the skill to diversify.
|
|
269
|
+
- **The strategy-alignment tiebreaker is bounded.** Maximum bonus is `+0.75` (`0.5 + 0.25`) and only applies when `|Δbase_score| ≤ 0.05`. The bonus must NEVER override a clear base-score winner.
|
|
270
|
+
|
|
271
|
+
## Escalation
|
|
272
|
+
|
|
273
|
+
- **User wants the artifact converted to a spec automatically.** Refuse; cite the Iron Law. Offer `/harness:brainstorming "<top-pick title>"` as the next step.
|
|
274
|
+
- **STRATEGY.md is present but invalid.** Print the validation error verbatim; do not block. Suggest `/harness:strategy` and continue with `strategy_grounded: false`.
|
|
275
|
+
- **User insists on `N > 25`.** Clamp to 25 and inform; offer to chain a second run with a different focus argument.
|
|
276
|
+
- **User insists every idea is `medium` on all three axes.** Push back once: "If everything is medium, ranking is uninformative — what is your highest-impact vs. highest-confidence outlier?" If they decline to differentiate, write the artifact anyway with a frontmatter `quality_flag: undifferentiated` note.
|
|
277
|
+
- **Output directory cannot be created.** Surface the filesystem error verbatim. Do not silently write to a fallback path.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Harness Ideate — Scoring Reference
|
|
2
|
+
|
|
3
|
+
Single reference consumed by Phase 4 RANK of `SKILL.md`. The skill never duplicates these numbers inline; it cites this file. Keeping the formula here lets future tweaks land in one place without rewriting every example in `SKILL.md`.
|
|
4
|
+
|
|
5
|
+
## Base formula
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
base_score = (impact × confidence) ÷ effort
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Each axis is one of `low`, `medium`, `high`, mapped to a small integer:
|
|
12
|
+
|
|
13
|
+
| Token | Numeric |
|
|
14
|
+
| -------- | ------- |
|
|
15
|
+
| `low` | 1 |
|
|
16
|
+
| `medium` | 2 |
|
|
17
|
+
| `high` | 3 |
|
|
18
|
+
|
|
19
|
+
The mapping is the SAME for `impact`, `confidence`, and `effort`. Use it everywhere.
|
|
20
|
+
|
|
21
|
+
### Worked example
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
impact: high (3)
|
|
25
|
+
confidence: medium (2)
|
|
26
|
+
effort: medium (2)
|
|
27
|
+
|
|
28
|
+
base_score = (3 × 2) ÷ 2 = 3.0
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Range of `base_score`: `[1 × 1 ÷ 3 ≈ 0.33, 3 × 3 ÷ 1 = 9.0]`. Higher is better.
|
|
32
|
+
|
|
33
|
+
## Strategy-alignment tiebreaker
|
|
34
|
+
|
|
35
|
+
When `STRATEGY.md` was loaded successfully in Phase 1 GROUND, an alignment bonus is computed per candidate:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
alignment_bonus =
|
|
39
|
+
(premise plausibly advances a Tracks bullet ? 0.5 : 0)
|
|
40
|
+
+ (premise/persona references Target problem or Our approach ? 0.25 : 0)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The maximum possible bonus is **`+0.75`** (`0.5 + 0.25`). When `STRATEGY.md` is absent or invalid, `alignment_bonus` is `0` for every candidate and this section is skipped entirely.
|
|
44
|
+
|
|
45
|
+
### Bounded application
|
|
46
|
+
|
|
47
|
+
The bonus is a **tiebreaker, not a multiplier**:
|
|
48
|
+
|
|
49
|
+
- Compute `base_score` for every candidate.
|
|
50
|
+
- Sort by `base_score` descending.
|
|
51
|
+
- For each adjacent pair where `|base_score_n − base_score_{n-1}| ≤ 0.05`, apply the alignment bonus to break the tie:
|
|
52
|
+
- `final_score = base_score + alignment_bonus` for the candidate whose pair-mate is within `0.05`.
|
|
53
|
+
- The bonus is added to BOTH candidates in the tie window; the higher final score wins.
|
|
54
|
+
- For pairs where `|Δbase_score| > 0.05`, the base score determines order — the bonus is recorded in the artifact for transparency but does NOT change the rank.
|
|
55
|
+
|
|
56
|
+
The `0.05` threshold mirrors `harness-roadmap-pilot`'s tiebreaker contract intentionally — same bounded-tiebreaker shape, different domain (ranking ideas vs. ranking roadmap candidates). Aligning the threshold keeps users from learning two different "close enough" rules for two adjacent skills.
|
|
57
|
+
|
|
58
|
+
### Anti-patterns the bonded cap rejects
|
|
59
|
+
|
|
60
|
+
| Failure mode | Why the cap rejects it |
|
|
61
|
+
| --------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
|
62
|
+
| "Idea A scores 2.0, Idea B scores 5.0; B aligns with strategy, A doesn't" | ` | 5.0 − 2.0 | = 3.0`, way outside the `0.05` window. No bonus applied. Base score wins. Cap protects rankings from over-fitting to strategy. |
|
|
63
|
+
| "Every idea aligns; I'll add `+0.75` to all and call it ranked" | Bonus is only applied within tie windows. Universal alignment yields the same final ordering as the base score. The cap forces ranking to come from the base formula first. |
|
|
64
|
+
| "STRATEGY.md exists but is invalid; I should still apply the bonus heuristically" | Soft-fail: `alignment_bonus = 0` for every candidate when strategy is absent OR invalid. The skill never invents alignment when it cannot read the source. |
|
|
65
|
+
| "I'll widen the threshold to `0.5` so more ideas qualify" | Threshold is a constant in this file, NOT a parameter. Widening means updating this reference and re-justifying the change in an ADR (mirrors the roadmap-pilot decision). |
|
|
66
|
+
|
|
67
|
+
## Persistence — what lands in the artifact
|
|
68
|
+
|
|
69
|
+
For every candidate the persisted `docs/ideation/<slug>-YYYY-MM-DD.md` records, at minimum:
|
|
70
|
+
|
|
71
|
+
- `base_score` (always)
|
|
72
|
+
- `alignment_bonus` (records the bonus value; `0` when strategy is absent or no signals matched)
|
|
73
|
+
- `final_score` (equals `base_score + alignment_bonus` IF the bonus was applied for tiebreak; otherwise equals `base_score` — the artifact MUST note which case applies via a one-line rationale)
|
|
74
|
+
- Whichever `Tracks` bullet or `Target problem` / `Our approach` phrase the alignment cited (verbatim) — citations are mandatory when `alignment_bonus > 0`
|
|
75
|
+
|
|
76
|
+
The artifact's frontmatter records `ranking_formula` verbatim so a future reader reproduces the order without rerunning the skill.
|
|
77
|
+
|
|
78
|
+
## Boundary with `harness-roadmap-pilot`
|
|
79
|
+
|
|
80
|
+
| Aspect | `harness-ideate` | `harness-roadmap-pilot` |
|
|
81
|
+
| ----------------------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
|
|
82
|
+
| What it ranks | Fresh candidate ideas generated in-skill | Existing roadmap entries from `docs/roadmap.md` |
|
|
83
|
+
| Base formula | `(impact × confidence) ÷ effort` (1/2/3 mapping) | `position × 0.5 + dependents × 0.3 + affinity × 0.2` |
|
|
84
|
+
| Tiebreaker threshold | `0.05` | `0.05` |
|
|
85
|
+
| Max alignment bonus | `+0.75` | `+0.75` |
|
|
86
|
+
| When STRATEGY is absent | Skip alignment entirely; rank by base score only; record `strategy_grounded: false` in artifact frontmatter | Skip alignment entirely; rank by base score only; no rationale citation |
|
|
87
|
+
|
|
88
|
+
The two skills share the bounded-tiebreaker contract on purpose. If the threshold or max bonus changes in one, update both — and add an ADR explaining why.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
name: harness-ideate
|
|
2
|
+
version: "0.1.0"
|
|
3
|
+
description: Pre-brainstorm ideation phase. Generates N candidate ideas grounded in STRATEGY.md (when present), critiques each against its strongest objection, ranks by (impact × confidence) ÷ effort with a bounded strategy-alignment tiebreaker, and writes a single ranked Markdown artifact to docs/ideation/[slug]-YYYY-MM-DD.md. Produces ranked ideation — never specs, plans, or code. harness-brainstorming consumes the output.
|
|
4
|
+
stability: static
|
|
5
|
+
cognitive_mode: divergent-generator
|
|
6
|
+
triggers:
|
|
7
|
+
- manual
|
|
8
|
+
platforms:
|
|
9
|
+
- claude-code
|
|
10
|
+
- gemini-cli
|
|
11
|
+
- cursor
|
|
12
|
+
- codex
|
|
13
|
+
tools:
|
|
14
|
+
- Bash
|
|
15
|
+
- Read
|
|
16
|
+
- Write
|
|
17
|
+
- Edit
|
|
18
|
+
- Glob
|
|
19
|
+
- Grep
|
|
20
|
+
cli:
|
|
21
|
+
command: harness skill run harness-ideate
|
|
22
|
+
args:
|
|
23
|
+
- name: focus
|
|
24
|
+
description: One-line focus argument that anchors candidate generation (e.g., "onboarding for plugin-only users"). Used as the ideation topic and slug source.
|
|
25
|
+
required: false
|
|
26
|
+
- name: count
|
|
27
|
+
description: Number of candidate ideas to generate (default 10, min 5, max 25).
|
|
28
|
+
required: false
|
|
29
|
+
mcp:
|
|
30
|
+
tool: run_skill
|
|
31
|
+
input:
|
|
32
|
+
skill: harness-ideate
|
|
33
|
+
path: string
|
|
34
|
+
type: rigid
|
|
35
|
+
tier: 2
|
|
36
|
+
phases:
|
|
37
|
+
- name: ground
|
|
38
|
+
description: Read STRATEGY.md if present at repo root (grounding); read the focus argument; confirm the topic with the user.
|
|
39
|
+
required: true
|
|
40
|
+
- name: generate
|
|
41
|
+
description: Produce N candidate ideas with per-idea fields (premise, persona, complexity, key risk, impact, confidence, effort).
|
|
42
|
+
required: true
|
|
43
|
+
- name: critique
|
|
44
|
+
description: For each idea identify the strongest objection; user picks which objections to answer.
|
|
45
|
+
required: true
|
|
46
|
+
- name: rank
|
|
47
|
+
description: Score by (impact × confidence) ÷ effort using a 1/2/3 mapping for low/medium/high; apply strategy-alignment as a bounded tiebreaker bonus when STRATEGY.md is present.
|
|
48
|
+
required: true
|
|
49
|
+
- name: write
|
|
50
|
+
description: Persist the ranked artifact to docs/ideation/[slug]-YYYY-MM-DD.md (kebab-case slug ≤30 chars, 6-char hash suffix on collision).
|
|
51
|
+
required: true
|
|
52
|
+
state:
|
|
53
|
+
persistent: true
|
|
54
|
+
files:
|
|
55
|
+
- docs/ideation/
|
|
56
|
+
depends_on: []
|
|
57
|
+
related_skills:
|
|
58
|
+
- harness-strategy
|
|
59
|
+
- harness-brainstorming
|
|
60
|
+
keywords:
|
|
61
|
+
- ideation
|
|
62
|
+
- pre-brainstorm
|
|
63
|
+
- candidate-generation
|
|
64
|
+
- impact-confidence-effort
|
|
65
|
+
- strategic-anchor
|
|
66
|
+
- compound-engineering
|
|
@@ -294,7 +294,16 @@ Report progress: `**[Phase 2/4]** DECOMPOSE — mapping file structure and creat
|
|
|
294
294
|
5. **Check failures log.** Read `.harness/failures.md`. If planned approaches match known failures, flag them.
|
|
295
295
|
6. **Run soundness review.** Invoke `harness-soundness-review --mode plan` against the draft. Do not proceed until the review converges with no remaining issues.
|
|
296
296
|
7. **Write the plan to `docs/changes/<topic>/plans/`.** Naming: `YYYY-MM-DD-<feature-name>-plan.md`. Resolve `<topic>` from the spec path — if the spec lives at `docs/changes/<topic>/proposal.md`, the plan goes in the sibling `plans/` directory. If the spec is not under `docs/changes/`, fall back to `docs/plans/` and flag the spec location for human review. Create directories as needed.
|
|
297
|
-
8. **
|
|
297
|
+
8. **Commit plan artifact.** Immediately after writing the plan, commit it so the paper trail enters git history at planning time, not after execution:
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
git add docs/changes/<topic>/plans/YYYY-MM-DD-<feature-name>-plan.md
|
|
301
|
+
git commit -m "docs(<topic>): add plan"
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Use `docs/plans/` if the spec is not under `docs/changes/<topic>/`. Do not skip — `harness-execution` commits only implementation files, so a plan uncommitted here stays untracked until someone notices. If a pre-commit hook reformats the file, re-add and re-commit.
|
|
305
|
+
|
|
306
|
+
9. **Write handoff.** Write to the session-scoped path when session slug is known, otherwise fall back to global path:
|
|
298
307
|
- Session-scoped (preferred): `.harness/sessions/<session-slug>/handoff.json`
|
|
299
308
|
- Global (fallback, **deprecated**): `.harness/handoff.json`
|
|
300
309
|
|
|
@@ -302,11 +311,11 @@ Report progress: `**[Phase 2/4]** DECOMPOSE — mapping file structure and creat
|
|
|
302
311
|
|
|
303
312
|
Fields: `fromSkill`, `phase`, `summary`, `completed`, `pending`, `concerns`, `decisions`, `contextKeywords`.
|
|
304
313
|
|
|
305
|
-
|
|
314
|
+
10. **Write session summary (if session is known).** Call `writeSessionSummary` with skill, status, plan path, keyContext, nextStep. Skip if no session slug.
|
|
306
315
|
|
|
307
|
-
|
|
316
|
+
11. **Request plan sign-off:** Use `emit_interaction` (type: `confirmation`) with plan path, task count, and time estimate.
|
|
308
317
|
|
|
309
|
-
|
|
318
|
+
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).
|
|
310
319
|
|
|
311
320
|
---
|
|
312
321
|
|
|
@@ -392,6 +401,7 @@ When referencing existing code in task specs, cite evidence using `file:line` fo
|
|
|
392
401
|
|
|
393
402
|
- **`harness validate`** — Run in Phase 4 (before writing plan) and included in every task.
|
|
394
403
|
- **`harness check-deps`** — Referenced in tasks adding imports or creating modules.
|
|
404
|
+
- **Plan commit** — After writing the plan (Phase 4 Step 8), commit `docs/changes/<topic>/plans/YYYY-MM-DD-<feature-name>-plan.md` so the paper trail enters git history at planning time. `harness-execution` does not backfill — see issue #487.
|
|
395
405
|
- **Plan location** — `docs/changes/<topic>/plans/YYYY-MM-DD-<feature-name>-plan.md` when the spec lives under `docs/changes/<topic>/proposal.md`; otherwise `docs/plans/` as a fallback.
|
|
396
406
|
- **Handoff** — Once approved, invoke harness-execution for task-by-task implementation.
|
|
397
407
|
- **Session directory** — Session-scoped writes go to `.harness/sessions/<slug>/`. Structure: `handoff.json`, `state.json`, `artifacts.json` (registry of spec/plan paths and produced file lists). Global `.harness/handoff.json` is deprecated for session-aware invocations.
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
Read `references/interview.md` for the SMART pushback rules and the READ-WRITE-DB rejection rule. Both are mandatory.
|
|
32
32
|
|
|
33
|
-
1. **Seed from STRATEGY.md.**
|
|
33
|
+
1. **Seed from STRATEGY.md.** Call `seed_pulse_from_strategy({ path: process.cwd() })` on the harness MCP server. Capture `{ name, keyMetrics, warnings }` — the server does the file read and bullet extraction internally. Fallback when the MCP server is unavailable: `node -e "import('@harness-engineering/core').then(m => console.log(JSON.stringify(m.seedFromStrategy({}))))"` — only works when `@harness-engineering/core` is resolvable from the project.
|
|
34
34
|
- Surface `warnings` to the user verbatim.
|
|
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.
|
|
@@ -56,13 +56,9 @@ Read `references/interview.md` for the SMART pushback rules and the READ-WRITE-D
|
|
|
56
56
|
|
|
57
57
|
9. **Confirm the assembled config.** Show the user the proposed `pulse:` block; ask for confirmation.
|
|
58
58
|
|
|
59
|
-
10. **Write the config.**
|
|
59
|
+
10. **Write the config.** Call `write_pulse_config({ path: process.cwd(), config })` on the harness MCP server. The `config` argument is the assembled `PulseConfig` JSON. The MCP tool validates against `PulseConfigSchema` and refuses to touch disk on schema failure; passing the config as a JSON parameter (not through a shell) means user-supplied prose never crosses the shell tokenizer — no quoting, backtick, or `$VAR` hazard. The writer preserves all other config keys and writes `harness.config.json.bak` on first call.
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
echo '<json-blob>' | node -e "import('@harness-engineering/core').then(m => m.writePulseConfig(JSON.parse(require('fs').readFileSync(0, 'utf-8')), { configPath: 'harness.config.json' })).catch(err => { console.error(err.message); process.exit(1); })"
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
The writer preserves all other config keys and writes a `.bak`.
|
|
61
|
+
Fallback for environments without the MCP server (only works when `@harness-engineering/core` is resolvable from the project): `echo '<json-blob>' | node -e "import('@harness-engineering/core').then(m => m.writePulseConfig(JSON.parse(require('fs').readFileSync(0, 'utf-8')), { configPath: 'harness.config.json' }))"`.
|
|
66
62
|
|
|
67
63
|
11. **Offer to register the `product-pulse` maintenance task.** Deferred: Phase 6 of the spec wires it. For now, surface "the daily 8am `product-pulse` task will be registered automatically once Phase 6 of the feedback-loops spec ships; you can also run pulse on demand with `/harness:pulse [window]` once Phase 4 ships."
|
|
68
64
|
|
|
@@ -80,12 +76,12 @@ Stub: when `pulse.enabled === true`, this phase will dispatch analytics/tracing/
|
|
|
80
76
|
|
|
81
77
|
## Harness Integration
|
|
82
78
|
|
|
83
|
-
- **`harness validate`** — Run after `
|
|
84
|
-
-
|
|
85
|
-
- `
|
|
86
|
-
- `
|
|
87
|
-
|
|
88
|
-
- `
|
|
79
|
+
- **`harness validate`** — Run after `write_pulse_config`; the existing pulse-schema validator catches malformed blocks.
|
|
80
|
+
- **Harness MCP tools consumed by this skill** (canonical execution path — no project-local `@harness-engineering/core` required):
|
|
81
|
+
- `seed_pulse_from_strategy({ path })` — defensive STRATEGY.md reader; returns `{ name, keyMetrics, warnings }`.
|
|
82
|
+
- `write_pulse_config({ path, config })` — atomic config update with .bak. Validates against `PulseConfigSchema`.
|
|
83
|
+
- **`@harness-engineering/core`** primitives the MCP tools wrap (only directly relevant when developing inside the monorepo or when the MCP server is unavailable):
|
|
84
|
+
- `writePulseConfig(config, { configPath })`, `seedFromStrategy({ cwd })`, `getPulseAdapter(name)` / `listPulseAdapters()` (Phase 4 populates), `PulseConfigSchema` / `PII_FIELD_DENYLIST`.
|
|
89
85
|
- **Boundary with `harness-strategy`** — Strategy writes `STRATEGY.md`; pulse reads it to seed. Pulse never writes to `STRATEGY.md`.
|
|
90
86
|
- **Boundary with `harness-observability`** — Observability designs _what_ to instrument; pulse is the read-side companion that surfaces what was instrumented.
|
|
91
87
|
- **Decision 6 (read-only)** — Pulse refuses read-write DB credentials. Documented in `references/interview.md`.
|
|
@@ -106,7 +102,7 @@ Stub: when `pulse.enabled === true`, this phase will dispatch analytics/tracing/
|
|
|
106
102
|
- Phase 0: route to Phase 1.
|
|
107
103
|
- Phase 1.1: `seedFromStrategy` returns `{ name: null, keyMetrics: [], warnings: ['STRATEGY.md not found'] }`.
|
|
108
104
|
- Phase 1.2-7: prompt user; collect `lookbackDefault: '24h'`, `primaryEvent: 'session_started'`, `valueEvent: 'plan_completed'`, `sources.analytics: 'posthog'` (with adapter-availability warning), `sources.db.enabled: false`.
|
|
109
|
-
- Phase 1.10: `
|
|
105
|
+
- Phase 1.10: `write_pulse_config` writes the block; `.bak` saved.
|
|
110
106
|
- Phase 1.12: `harness validate` passes.
|
|
111
107
|
|
|
112
108
|
### Example: STRATEGY.md present with 3 Key metrics
|
|
@@ -127,7 +123,7 @@ Stub: when `pulse.enabled === true`, this phase will dispatch analytics/tracing/
|
|
|
127
123
|
|
|
128
124
|
- **READ-WRITE-DB rejection is non-negotiable.** No flag, no override, no "I know what I'm doing" path. Refuse and document.
|
|
129
125
|
- **SMART pushback is mandatory on every proposed metric/event.** Silently accepting a vague name pollutes the corpus.
|
|
130
|
-
- **`writePulseConfig` is the only sanctioned write path.** Do not hand-edit `harness.config.json`. The writer is the layer that preserves non-pulse keys and writes the .bak.
|
|
126
|
+
- **`write_pulse_config` (or `writePulseConfig` when invoked directly) is the only sanctioned write path.** Do not hand-edit `harness.config.json`. The writer is the layer that preserves non-pulse keys and writes the .bak.
|
|
131
127
|
- **`harness validate` must pass before exit.** A malformed `pulse:` block silently breaks the daily task once Phase 4 ships.
|
|
132
128
|
|
|
133
129
|
## Escalation
|
|
@@ -135,4 +131,4 @@ Stub: when `pulse.enabled === true`, this phase will dispatch analytics/tracing/
|
|
|
135
131
|
- **User insists on read-write DB credentials:** Refuse. Set `sources.db.enabled: false`. Stop.
|
|
136
132
|
- **Adapter not registered for a chosen provider:** Warn, record the choice, continue. The runtime gate (Phase 4) refuses to run until the adapter ships.
|
|
137
133
|
- **STRATEGY.md frontmatter is malformed but H1 is present:** Use H1 as `name` and surface a warning. If neither is parseable, prompt the user.
|
|
138
|
-
- **`writePulseConfig` throws:** Report the validator error verbatim. Do not retry without user fix.
|
|
134
|
+
- **`write_pulse_config` returns `{ written: false, error }` (or `writePulseConfig` throws directly):** Report the validator error verbatim. Do not retry without user fix.
|
|
@@ -58,6 +58,30 @@ Top candidates (scored by position 50%, dependents 30%, affinity 20%):
|
|
|
58
58
|
- Read the spec's Success Criteria section
|
|
59
59
|
- Assess effort and impact from the spec content
|
|
60
60
|
|
|
61
|
+
1a. **Read `STRATEGY.md` if present at repo root (strategy-alignment input).** Use a Node one-liner that calls `validateStrategy` from `@harness-engineering/core`, then (when valid) `parseStrategyDoc` + `asStrategyDoc`:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
node -e "import('@harness-engineering/core').then(async m => {
|
|
65
|
+
const v = await m.validateStrategy(process.cwd());
|
|
66
|
+
if (!v.present || !v.valid) { console.log(JSON.stringify({ grounded: false })); return; }
|
|
67
|
+
const raw = require('fs').readFileSync('STRATEGY.md', 'utf-8');
|
|
68
|
+
console.log(JSON.stringify({ grounded: true, doc: m.asStrategyDoc(m.parseStrategyDoc(raw)) }));
|
|
69
|
+
})"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
When `grounded: true`, capture the `Target problem`, `Our approach`, and `Tracks` section bodies. For each top-3 candidate, compute a strategy-alignment score:
|
|
73
|
+
|
|
74
|
+
- `+0.5` if the candidate's feature name or spec keywords plausibly advance one of the `Tracks` (case-insensitive substring or paraphrase match)
|
|
75
|
+
- `+0.25` if the candidate's spec Overview cites the `Target problem` or `Our approach` verbatim or near-verbatim
|
|
76
|
+
- `0` otherwise
|
|
77
|
+
|
|
78
|
+
The alignment score is a **tiebreaker bonus**, NEVER a hard filter:
|
|
79
|
+
|
|
80
|
+
- Apply only when the absolute difference between two candidates' base scores is `≤ 0.05` (items score similarly on `position × 0.5 + dependents × 0.3 + affinity × 0.2`).
|
|
81
|
+
- Never let the bonus override a meaningful base-score difference.
|
|
82
|
+
- When alignment is applied, cite it in the recommendation rationale ("Tiebreaker: aligned with track 'pulse-reports' from STRATEGY.md").
|
|
83
|
+
- When `STRATEGY.md` is absent or invalid, skip this step silently; the recommendation proceeds without a strategy tiebreaker.
|
|
84
|
+
|
|
61
85
|
1b. Read the most recent pulse report (if any):
|
|
62
86
|
|
|
63
87
|
- List entries in `docs/pulse-reports/` and **filter to those matching the
|
|
@@ -166,6 +190,7 @@ Proceed with Feature A? (y/n/pick another)
|
|
|
166
190
|
- **`scoreRoadmapCandidates`** -- Underlying file-backed scoring algorithm. Prefer `scoreRoadmapCandidatesForMode` from the skill; direct callers in file-backed-only code paths can still use this.
|
|
167
191
|
- **`manage_roadmap update`** -- Used for assignment. Supports `assignee` field which delegates to `assignFeature` internally, handles history tracking, and automatically triggers external sync (GitHub Issues). In file-less mode, `manage_roadmap` dispatches through the tracker; the skill flow is unchanged.
|
|
168
192
|
- **`emit_interaction`** -- Used for the skill transition at the end. Transitions to `harness:brainstorming` (no spec) or `harness:autopilot` (spec exists).
|
|
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.
|
|
169
194
|
- **`harness validate`** -- Run after assignment is written.
|
|
170
195
|
|
|
171
196
|
## Success Criteria
|
|
@@ -178,15 +203,18 @@ Proceed with Feature A? (y/n/pick another)
|
|
|
178
203
|
6. Reassignment produces two history records (unassigned + assigned)
|
|
179
204
|
7. Transition routes to brainstorming (no spec) or autopilot (spec exists)
|
|
180
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.
|
|
181
|
-
9. `
|
|
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.
|
|
207
|
+
10. When `STRATEGY.md` is absent or invalid, the skill completes without error and no strategy-alignment rationale appears in the output.
|
|
208
|
+
11. `harness validate` passes after all changes
|
|
182
209
|
|
|
183
210
|
## Rationalizations to Reject
|
|
184
211
|
|
|
185
|
-
| Rationalization | Reality
|
|
186
|
-
| ----------------------------------------------------------------------------------------------------------------------- |
|
|
187
|
-
| "The top-scored candidate is obviously correct, so I can assign it without asking the human" | The Iron Law: never assign or transition without the human confirming the recommendation first.
|
|
188
|
-
| "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.
|
|
189
|
-
| "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.
|
|
212
|
+
| Rationalization | Reality |
|
|
213
|
+
| ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
214
|
+
| "The top-scored candidate is obviously correct, so I can assign it without asking the human" | The Iron Law: never assign or transition without the human confirming the recommendation first. |
|
|
215
|
+
| "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. |
|
|
216
|
+
| "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. |
|
|
217
|
+
| "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. |
|
|
190
218
|
|
|
191
219
|
## Examples
|
|
192
220
|
|