@harness-engineering/cli 2.7.1 → 3.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/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-audit-harness-strength/SKILL.md +188 -0
- package/dist/agents/skills/claude-code/harness-audit-harness-strength/skill.yaml +54 -0
- package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +2 -0
- package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +58 -12
- 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-execution/SKILL.md +1 -1
- package/dist/agents/skills/claude-code/harness-git-workflow/SKILL.md +2 -0
- package/dist/agents/skills/claude-code/harness-ideate/SKILL.md +279 -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-knowledge-pipeline/SKILL.md +2 -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/SKILL.md +62 -4
- package/dist/agents/skills/claude-code/harness-roadmap-pilot/SKILL.md +36 -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/harness-test-advisor/SKILL.md +80 -2
- package/dist/agents/skills/claude-code/harness-test-advisor/skill.yaml +4 -1
- package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +86 -18
- package/dist/agents/skills/claude-code/initialize-harness-project/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/outcome-eval/SKILL.md +97 -0
- package/dist/agents/skills/claude-code/outcome-eval/skill.yaml +51 -0
- 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-audit-harness-strength/SKILL.md +188 -0
- package/dist/agents/skills/codex/harness-audit-harness-strength/skill.yaml +54 -0
- package/dist/agents/skills/codex/harness-autopilot/SKILL.md +2 -0
- package/dist/agents/skills/codex/harness-brainstorming/SKILL.md +58 -12
- 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-execution/SKILL.md +1 -1
- package/dist/agents/skills/codex/harness-git-workflow/SKILL.md +2 -0
- package/dist/agents/skills/codex/harness-ideate/SKILL.md +279 -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-knowledge-pipeline/SKILL.md +2 -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/SKILL.md +62 -4
- package/dist/agents/skills/codex/harness-roadmap-pilot/SKILL.md +36 -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/harness-test-advisor/SKILL.md +80 -2
- package/dist/agents/skills/codex/harness-test-advisor/skill.yaml +4 -1
- package/dist/agents/skills/codex/initialize-harness-project/SKILL.md +86 -18
- package/dist/agents/skills/codex/initialize-harness-project/skill.yaml +1 -0
- package/dist/agents/skills/codex/outcome-eval/SKILL.md +97 -0
- package/dist/agents/skills/codex/outcome-eval/skill.yaml +51 -0
- 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-audit-harness-strength/SKILL.md +188 -0
- package/dist/agents/skills/cursor/harness-audit-harness-strength/skill.yaml +54 -0
- package/dist/agents/skills/cursor/harness-autopilot/SKILL.md +2 -0
- package/dist/agents/skills/cursor/harness-brainstorming/SKILL.md +58 -12
- 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-execution/SKILL.md +1 -1
- package/dist/agents/skills/cursor/harness-git-workflow/SKILL.md +2 -0
- package/dist/agents/skills/cursor/harness-ideate/SKILL.md +279 -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-knowledge-pipeline/SKILL.md +2 -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/SKILL.md +62 -4
- package/dist/agents/skills/cursor/harness-roadmap-pilot/SKILL.md +36 -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/harness-test-advisor/SKILL.md +80 -2
- package/dist/agents/skills/cursor/harness-test-advisor/skill.yaml +4 -1
- package/dist/agents/skills/cursor/initialize-harness-project/SKILL.md +86 -18
- package/dist/agents/skills/cursor/initialize-harness-project/skill.yaml +1 -0
- package/dist/agents/skills/cursor/outcome-eval/SKILL.md +97 -0
- package/dist/agents/skills/cursor/outcome-eval/skill.yaml +51 -0
- 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-audit-harness-strength/SKILL.md +188 -0
- package/dist/agents/skills/gemini-cli/harness-audit-harness-strength/skill.yaml +54 -0
- package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +2 -0
- package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +58 -12
- 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-execution/SKILL.md +1 -1
- package/dist/agents/skills/gemini-cli/harness-git-workflow/SKILL.md +2 -0
- package/dist/agents/skills/gemini-cli/harness-ideate/SKILL.md +279 -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-knowledge-pipeline/SKILL.md +2 -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/SKILL.md +62 -4
- package/dist/agents/skills/gemini-cli/harness-roadmap-pilot/SKILL.md +36 -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/harness-test-advisor/SKILL.md +80 -2
- package/dist/agents/skills/gemini-cli/harness-test-advisor/skill.yaml +4 -1
- package/dist/agents/skills/gemini-cli/initialize-harness-project/SKILL.md +86 -18
- package/dist/agents/skills/gemini-cli/initialize-harness-project/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/outcome-eval/SKILL.md +97 -0
- package/dist/agents/skills/gemini-cli/outcome-eval/skill.yaml +51 -0
- package/dist/agents/skills/package.json +1 -1
- package/dist/agents/skills/tests/harness-strategy.test.ts +145 -0
- package/dist/agents/skills/tests/harness-test-advisor.test.ts +94 -0
- package/dist/agents-md-XOJE5ETA.js +13 -0
- package/dist/analyzer-V633GUHY-MBCQWKDU.js +26 -0
- package/dist/{architecture-LUR2I67H.js → architecture-JEZPJ725.js} +6 -6
- package/dist/{assess-project-OJWECOP2.js → assess-project-RHXOQNMM.js} +1 -1
- package/dist/bin/harness-mcp.js +17 -17
- package/dist/bin/harness.js +27 -27
- package/dist/{check-phase-gate-HS5KYLRO.js → check-phase-gate-GNDOMS35.js} +6 -6
- package/dist/{chunk-6UHDQP2N.js → chunk-2N4OENGE.js} +1 -1
- package/dist/{chunk-O2ASYKA6.js → chunk-3ISHDWO7.js} +2 -2
- package/dist/{chunk-GGSNWH7P.js → chunk-527G27VI.js} +5 -5
- package/dist/{chunk-N5NSSLMU.js → chunk-6WQCLCBO.js} +2 -2
- package/dist/{chunk-OH3NXXUY.js → chunk-BDGTZRZ6.js} +11 -1
- package/dist/{chunk-Z3TMCCZB.js → chunk-BYVT5LVO.js} +9 -9
- package/dist/{chunk-TIH53QXY.js → chunk-CLI4K2CH.js} +1 -1
- package/dist/{chunk-VSIRUZQP.js → chunk-DE5U6KOL.js} +2 -2
- package/dist/{chunk-FXZI6NJ2.js → chunk-GGKRA7A7.js} +51 -4
- package/dist/{chunk-RJ2WEES5.js → chunk-GSP2XIVS.js} +2 -2
- package/dist/{chunk-CZPOPMMI.js → chunk-HEIMJJI4.js} +3 -3
- package/dist/{chunk-7AF6C5GE.js → chunk-HWTUUQOW.js} +3 -3
- package/dist/{chunk-FC4JPM6W.js → chunk-KAJOS3BA.js} +3 -3
- package/dist/{chunk-NIVWM7OW.js → chunk-MGUPSE6D.js} +10 -10
- package/dist/{chunk-WZY5U6NS.js → chunk-N24HCQA4.js} +3351 -887
- package/dist/{chunk-Y4T6ENKQ.js → chunk-N55WOGN3.js} +86 -17
- package/dist/{chunk-INBTDBV2.js → chunk-NWLGL3IR.js} +1 -1
- package/dist/{chunk-FEKBXX2J.js → chunk-ONCPJGHY.js} +9 -9
- package/dist/{chunk-PTHX545Q.js → chunk-PC2R5RUJ.js} +2 -2
- package/dist/{chunk-H2ZJOJ7A.js → chunk-PP6ZRL5T.js} +316 -42
- package/dist/{chunk-LECXPXS3.js → chunk-QBC7DI4Q.js} +2 -2
- package/dist/{chunk-B2VAYLYI.js → chunk-UX3PQKVZ.js} +8 -3
- package/dist/{chunk-7PLIWP7U.js → chunk-WWEVS7RO.js} +4409 -743
- package/dist/{chunk-LGYXR2KZ.js → chunk-XFU6SB2Q.js} +1122 -689
- package/dist/{chunk-KN3EMDZ5.js → chunk-XX4OLNWQ.js} +23 -3
- package/dist/{chunk-VI4IS55S.js → chunk-YQSYCBAH.js} +6 -6
- package/dist/{chunk-LYIPI2SJ.js → chunk-Z4AWEIBY.js} +6 -6
- package/dist/{ci-workflow-MDSTHJOY.js → ci-workflow-ORZ4F45F.js} +5 -5
- package/dist/{dist-E3SAAHCM.js → dist-ICW4QUEW.js} +5 -1
- package/dist/{dist-72ID44UE.js → dist-LHINSVK4.js} +136 -4
- package/dist/{dist-R3TOOPJ7.js → dist-OWHMNL4W.js} +1 -1
- package/dist/{docs-2RFOJ6XY.js → docs-AU3DXFFO.js} +6 -6
- package/dist/engine-6GPWOYQH.js +13 -0
- package/dist/{entropy-3UX6644G.js → entropy-VLKDRMRT.js} +5 -5
- package/dist/{feedback-CVCFYND4.js → feedback-YXYY44ZC.js} +1 -1
- package/dist/{generate-agent-definitions-HZ3XENWO.js → generate-agent-definitions-XIHQPKG3.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/hooks/cost-tracker.js +29 -6
- package/dist/index.d.ts +202 -0
- package/dist/index.js +27 -27
- package/dist/{loader-6RHWU5FH.js → loader-YAN56MT3.js} +5 -5
- package/dist/{mcp-OYR26JDI.js → mcp-RK3SFVYB.js} +17 -17
- package/dist/{performance-JJMIRXCH.js → performance-64DPTLLQ.js} +6 -6
- package/dist/{review-pipeline-BHQZIXWZ.js → review-pipeline-NENG6LW7.js} +5 -5
- package/dist/{runtime-DALTAVTN.js → runtime-FFIIRT2T.js} +5 -5
- package/dist/{scan-LYKLM4EQ.js → scan-P7YFKB77.js} +1 -1
- package/dist/{security-RMLMYFPB.js → security-3PIBN35B.js} +1 -1
- package/dist/templates/basic/harness.config.json.hbs +34 -0
- package/dist/templates/ci/README.md +86 -0
- package/dist/templates/ci/required-review.ruleset.json +20 -0
- package/dist/templates/ci/required-review.yml.hbs +57 -0
- package/dist/templates/ci/template.json +5 -0
- package/dist/templates/intermediate/harness.config.json.hbs +36 -0
- package/dist/templates/orchestrator/harness.orchestrator.md +9 -0
- package/dist/{tool-tiers-B7JC2XC3.js → tool-tiers-OKK5FE57.js} +2 -0
- package/dist/{validate-R7DZRDFK.js → validate-7IAF2ES3.js} +6 -6
- package/dist/validate-cross-check-QPSAOZKD.js +13 -0
- package/package.json +8 -8
- package/dist/agents-md-FKMKH6ZF.js +0 -13
- package/dist/analyzer-H3AHBFSL-KPOPJYRB.js +0 -26
- package/dist/engine-BSFKOGPN.js +0 -13
- package/dist/validate-cross-check-AUUZFNVL.js +0 -13
|
@@ -33,20 +33,22 @@ A reviewer who applies fixes is no longer reviewing — they are editing with re
|
|
|
33
33
|
The review runs as a 7-phase pipeline. Each phase has a clear input, output, and exit condition.
|
|
34
34
|
|
|
35
35
|
```
|
|
36
|
-
Phase 1: GATE --> Phase 2: MECHANICAL --> Phase 3: CONTEXT --> Phase
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
Phase 1: GATE --> Phase 2: MECHANICAL --> Phase 3: CONTEXT --> Phase 3.5: CALIBRATE
|
|
37
|
+
|
|
|
38
|
+
v
|
|
39
|
+
Phase 7: OUTPUT <-- Phase 6: DEDUP+MERGE <-- Phase 5: VALIDATE <-- Phase 4: FAN-OUT
|
|
39
40
|
```
|
|
40
41
|
|
|
41
|
-
| Phase | Tier | Purpose
|
|
42
|
-
| -------------- | ----- |
|
|
43
|
-
| 1. GATE | fast | Skip ineligible PRs (CI only)
|
|
44
|
-
| 2. MECHANICAL | none | Lint, typecheck, test, sec scan
|
|
45
|
-
| 3. CONTEXT | fast | Scope context per review domain
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
42
|
+
| Phase | Tier | Purpose | Exit Condition |
|
|
43
|
+
| -------------- | ----- | -------------------------------------------------- | ------------------------------------------------- |
|
|
44
|
+
| 1. GATE | fast | Skip ineligible PRs (CI only) | PR eligible, or exit with reason |
|
|
45
|
+
| 2. MECHANICAL | none | Lint, typecheck, test, sec scan | All pass -> continue; any fail -> report and stop |
|
|
46
|
+
| 3. CONTEXT | fast | Scope context per review domain | Context bundles assembled for each subagent |
|
|
47
|
+
| 3.5. CALIBRATE | none | Pick depth tier + activate conditional subagents | DepthCalibration recorded in PipelineContext |
|
|
48
|
+
| 4. FAN-OUT | mixed | Parallel review subagents (4 base + N conditional) | All subagents return ReviewFinding[] |
|
|
49
|
+
| 5. VALIDATE | none | Exclude mechanical dupes, verify | Unvalidated findings discarded |
|
|
50
|
+
| 6. DEDUP+MERGE | none | Group, merge, assign severity | Deduplicated finding list with merged evidence |
|
|
51
|
+
| 7. OUTPUT | none | Text output or GitHub comments | Review delivered, exit code set |
|
|
50
52
|
|
|
51
53
|
### Finding Schema
|
|
52
54
|
|
|
@@ -62,19 +64,35 @@ interface ReviewFinding {
|
|
|
62
64
|
suggestion?: string; // fix, if available
|
|
63
65
|
evidence: string[]; // supporting context from agent
|
|
64
66
|
validatedBy: 'mechanical' | 'graph' | 'heuristic';
|
|
67
|
+
// Additive — populated by the new conditional subagents only:
|
|
68
|
+
subagent?:
|
|
69
|
+
| 'compliance'
|
|
70
|
+
| 'bug'
|
|
71
|
+
| 'security'
|
|
72
|
+
| 'architecture'
|
|
73
|
+
| 'learnings'
|
|
74
|
+
| 'adversarial'
|
|
75
|
+
| 'typescript-strict'
|
|
76
|
+
| 'frontend-races';
|
|
77
|
+
confidence?: 'high' | 'medium' | 'low' | 25 | 50 | 75 | 100;
|
|
65
78
|
}
|
|
66
79
|
```
|
|
67
80
|
|
|
81
|
+
The two optional fields are additive — existing 4 agents leave them
|
|
82
|
+
undefined. Numeric `confidence` values follow the anchored rubric at
|
|
83
|
+
[references/confidence-rubric.md](references/confidence-rubric.md).
|
|
84
|
+
|
|
68
85
|
### Flags
|
|
69
86
|
|
|
70
|
-
| Flag | Effect
|
|
71
|
-
| ----------------- |
|
|
72
|
-
| `--comment` | Post inline comments to GitHub PR via `gh` CLI or GitHub MCP
|
|
73
|
-
| `--deep` | Pass `--deep` to `harness-security-review` for threat modeling
|
|
74
|
-
| `--no-mechanical` | Skip mechanical checks (useful if already run in CI)
|
|
75
|
-
| `--ci` | Enable eligibility gate, non-interactive output
|
|
76
|
-
| `--fast` | Skip learnings, fast-tier agents for all fan-out slots
|
|
77
|
-
| `--thorough` | Always load learnings, full roster + meta-judge, learnings in output
|
|
87
|
+
| Flag | Effect |
|
|
88
|
+
| ----------------- | ------------------------------------------------------------------------------------ |
|
|
89
|
+
| `--comment` | Post inline comments to GitHub PR via `gh` CLI or GitHub MCP |
|
|
90
|
+
| `--deep` | Pass `--deep` to `harness-security-review` for threat modeling |
|
|
91
|
+
| `--no-mechanical` | Skip mechanical checks (useful if already run in CI) |
|
|
92
|
+
| `--ci` | Enable eligibility gate, non-interactive output |
|
|
93
|
+
| `--fast` | Skip learnings, fast-tier agents for all fan-out slots |
|
|
94
|
+
| `--thorough` | Always load learnings, full roster + meta-judge, learnings in output |
|
|
95
|
+
| `--depth` | Override Phase 3.5 calibration: `quick`/`standard`/`deep`. `deep` activates all subs |
|
|
78
96
|
|
|
79
97
|
### Rigor Levels
|
|
80
98
|
|
|
@@ -254,7 +272,33 @@ git log --oneline -5 -- <affected-file>
|
|
|
254
272
|
|
|
255
273
|
Use to determine: **Hotspot?** (3+ changes in last 5 commits) **Recently refactored?** **Multiple authors?** **Last change was bugfix?** (yellow flag)
|
|
256
274
|
|
|
257
|
-
**Exit:** Context bundles assembled for all four domains. Continue to Phase
|
|
275
|
+
**Exit:** Context bundles assembled for all four domains. Continue to Phase 3.5.
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
### Phase 3.5: CALIBRATE DEPTH
|
|
280
|
+
|
|
281
|
+
**Tier:** none (mechanical) | **Purpose:** Pick a depth tier (Quick/Standard/Deep) from diff size + risk-keyword detection and decide which conditional subagents activate in Phase 4. The existing 4 agents always run; this phase only gates _additional_ work.
|
|
282
|
+
|
|
283
|
+
**Inputs:** `DiffInfo`, commit message, optional `--depth quick|standard|deep` override.
|
|
284
|
+
|
|
285
|
+
**Steps:**
|
|
286
|
+
|
|
287
|
+
1. **Count changed lines.** Sum `+`/`-` lines per file, excluding test files (`*.test.{ts,tsx,js,jsx}`, `__tests__/**`, `*.spec.{ts,tsx,js,jsx}`), generated files (`*.generated.{ts,tsx,js,jsx}`), lockfiles (`pnpm-lock.yaml`, `package-lock.json`, `yarn.lock`), and `dist/` / `build/` directories.
|
|
288
|
+
2. **Detect risk keywords.** Match the canonical keyword list from [references/risk-keywords.md](references/risk-keywords.md) against the diff content, file paths, and commit message (case-insensitive, whole-word for single-word keywords, substring for multi-word keywords like `external API`).
|
|
289
|
+
3. **Compute tier.**
|
|
290
|
+
- **Quick:** `< 50` lines AND `0` keywords
|
|
291
|
+
- **Standard:** `50–199` lines OR exactly `1` keyword
|
|
292
|
+
- **Deep:** `≥ 200` lines OR `≥ 2` keywords
|
|
293
|
+
4. **Compute activation set** (`adversarial`, `typescript-strict`, `frontend-races`):
|
|
294
|
+
- `adversarial` — active at Standard or Deep
|
|
295
|
+
- `typescript-strict` — active when the diff contains a non-test `.ts` or `.tsx` (excluding `*.d.ts`)
|
|
296
|
+
- `frontend-races` — active when `typescript-strict` is active AND the diff contains one of `.tsx`, `useEffect`, `useState`, `setTimeout`, `setInterval`, `addEventListener`, `data-controller=`
|
|
297
|
+
5. **Override (`--depth deep`)** — forces Deep tier and activates all three conditional subagents.
|
|
298
|
+
|
|
299
|
+
**Output:** `DepthCalibration { depth, changedLines, riskSignals, activations, overridden }` recorded in `PipelineContext`. Phase 7 displays the calibration result at the top of the review.
|
|
300
|
+
|
|
301
|
+
**Exit:** Calibration complete. Continue to Phase 4.
|
|
258
302
|
|
|
259
303
|
---
|
|
260
304
|
|
|
@@ -380,7 +424,48 @@ Reviews architectural violations, dependency direction, and design pattern compl
|
|
|
380
424
|
|
|
381
425
|
**Output:** `ReviewFinding[]` with `domain: 'architecture'`
|
|
382
426
|
|
|
383
|
-
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
#### Conditional Subagents (depth-gated, activated by Phase 3.5)
|
|
430
|
+
|
|
431
|
+
The dispatcher reads `PipelineContext.depthCalibration.activations` and runs only those listed. Each conditional subagent emits findings under existing domain values (`bug` or `architecture`) and populates `subagent` + `confidence` per the [confidence rubric](references/confidence-rubric.md).
|
|
432
|
+
|
|
433
|
+
##### Adversarial (strong tier) — activates at Standard or Deep
|
|
434
|
+
|
|
435
|
+
Constructs failure scenarios that fall _between_ the base 4 agents.
|
|
436
|
+
|
|
437
|
+
**Hunt categories:**
|
|
438
|
+
|
|
439
|
+
- **Assumption violation** — invariants the diff depends on but does not enforce (e.g., `JSON.parse` on untrusted input)
|
|
440
|
+
- **Composition failures** — two patterns correct alone that misbehave together (floating Promise chains, optional-chain calls)
|
|
441
|
+
- **Abuse cases** — adversarial input shapes the diff does not anticipate (unbounded `fetch`, accidentally enumerable surfaces)
|
|
442
|
+
- **Cascade chains (Deep only)** — single failures propagating through downstream callers (`new Promise` without `reject`)
|
|
443
|
+
|
|
444
|
+
**Output:** `ReviewFinding[]` with `domain: 'bug'`, `subagent: 'adversarial'`, `confidence: 50|75|100`.
|
|
445
|
+
|
|
446
|
+
##### TypeScript-strict (standard tier) — activates when a non-test `.ts`/`.tsx` is in the diff
|
|
447
|
+
|
|
448
|
+
**Hunt categories:**
|
|
449
|
+
|
|
450
|
+
- **Type holes that disable the checker** — explicit `any`, `// @ts-ignore`, `as unknown as T`, non-null assertions in non-`process.env` contexts
|
|
451
|
+
- **Refactor regression risk** — removed guards whose call sites have no test coverage
|
|
452
|
+
- **Existing-file complexity** — production TS files growing past 400 lines (Single Responsibility flag)
|
|
453
|
+
- **Five-second rule** — `handle*` / `process*` / `do*` style names that fail to predict behavior at the call site
|
|
454
|
+
|
|
455
|
+
**Output:** `ReviewFinding[]` with `domain: 'bug'` (type holes / regression) or `domain: 'architecture'` (complexity), `subagent: 'typescript-strict'`, `confidence: 50|75|100`.
|
|
456
|
+
|
|
457
|
+
##### Frontend-races (standard tier) — activates when TypeScript-strict is active AND an async-UI signal is present
|
|
458
|
+
|
|
459
|
+
**Hunt categories:**
|
|
460
|
+
|
|
461
|
+
- **Lifecycle cleanup gaps** — `setInterval` / `setTimeout` / `addEventListener` without matching cleanup in the same module
|
|
462
|
+
- **Hook timing mistakes** — `useEffect` immediately calling `setState` for a render-time-derivable value
|
|
463
|
+
- **Concurrent interactions** — overlapping clicks/requests, impossible-state booleans
|
|
464
|
+
- **Stale work** — `await fetch` followed by `setState` with no `AbortController` / `AbortSignal.timeout`
|
|
465
|
+
|
|
466
|
+
**Output:** `ReviewFinding[]` with `domain: 'bug'`, `subagent: 'frontend-races'`, `confidence: 50|75|100`.
|
|
467
|
+
|
|
468
|
+
**Exit:** All base agents + active conditional subagents returned findings. Continue to Phase 5.
|
|
384
469
|
|
|
385
470
|
---
|
|
386
471
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Confidence Rubric
|
|
2
|
+
|
|
3
|
+
> Anchored confidence rubric for `harness-code-review` conditional subagents. Numeric anchors avoid vague "high/medium/low" judgments. New subagents (`adversarial`, `typescript-strict`, `frontend-races`) populate `ReviewFinding.confidence` per this rubric. Existing 4 agents (compliance, bug, security, architecture) are not yet migrated.
|
|
4
|
+
|
|
5
|
+
## Anchors
|
|
6
|
+
|
|
7
|
+
| Score | Label | Definition |
|
|
8
|
+
| ----- | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
9
|
+
| `100` | Mechanical | Directly verifiable from the diff. The finding can be reproduced by quoting specific lines. No interpretation required. |
|
|
10
|
+
| `75` | Constructible scenario | The agent can describe a concrete sequence of inputs and observable outputs that triggers the issue. Every step is traceable to specific lines. |
|
|
11
|
+
| `50` | Judgment-based | The issue is real but partly judgment. Depends on assumptions about behavior outside the diff. |
|
|
12
|
+
| `25` | Speculative | Not supported by what is in the diff. **Suppress.** Agents must not emit. |
|
|
13
|
+
|
|
14
|
+
A finding with confidence below `25` must be discarded before it leaves the subagent.
|
|
15
|
+
|
|
16
|
+
## Per-agent worked examples
|
|
17
|
+
|
|
18
|
+
### `adversarial`
|
|
19
|
+
|
|
20
|
+
- **100 — Mechanical**: every step in the cascade is traceable to specific lines. _Example: a `useState` updater on line 32 schedules work that the cleanup on line 45 never cancels — both lines are quoted._
|
|
21
|
+
- **75 — Constructible scenario**: given specific input X, execution reaches line Y and produces wrong outcome Z. _Example: "If `parseDate('')` returns `null` (line 18), the chain at line 22 throws because there is no nullable check before `.toISOString()`."_
|
|
22
|
+
- **50 — Judgment-based**: scenario depends on external API behavior assumed but unverified. _Example: "If the remote service occasionally returns `5xx`, the retry loop at line 60 enters a tight spin." — the tight spin is real but the retry condition needs runtime evidence._
|
|
23
|
+
- **25 — Speculative**: "What if the caller ever does X?" with no diff evidence. _Suppress._
|
|
24
|
+
|
|
25
|
+
### `typescript-strict`
|
|
26
|
+
|
|
27
|
+
- **100 — Mechanical**: explicit `any`, `// @ts-ignore`, `as unknown as Foo`, or `unknown` assertion in the diff. _Example: `function load(x: any) { ... }` is quoted directly._
|
|
28
|
+
- **75 — Constructible scenario**: a refactor in the diff removes a guard that the type system relied on. _Example: "Removing the `if (user)` check on line 12 means line 14's access `user.id` is now reachable for `null`, but no test exercises this path."_
|
|
29
|
+
- **50 — Judgment-based**: naming or extraction quality calls. _Example: "Function `handleStuff` does three things — the five-second-rule fails for a future reader." — true but discretionary._
|
|
30
|
+
- **25 — Speculative**: "Could be improved someday." _Suppress._
|
|
31
|
+
|
|
32
|
+
### `frontend-races`
|
|
33
|
+
|
|
34
|
+
- **100 — Mechanical**: `setInterval` with no `clearInterval` in disconnect/unmount; `addEventListener` with no `removeEventListener`. _Example: `setInterval(tick, 1000)` on line 30 with no cleanup return in the `useEffect`._
|
|
35
|
+
- **75 — Constructible scenario**: race traceable to a specific interaction sequence. _Example: "Double-click on the submit button triggers two parallel network calls because `isSubmitting` is set inside an `await` (line 45) after the button stays clickable."_
|
|
36
|
+
- **50 — Judgment-based**: race depends on timing windows not fully forceable from diff. _Example: "If the server replies before the cleanup runs, the stale callback updates the new component instance." — possible but requires timing assumptions._
|
|
37
|
+
- **25 — Speculative**: "On a slow device this might race." _Suppress._
|
|
38
|
+
|
|
39
|
+
## How dedup uses confidence
|
|
40
|
+
|
|
41
|
+
Phase 6 DEDUP+MERGE prefers the higher-`severity` finding when two agents flag the same line. On a severity tie, the finding with explicit `confidence` set wins. When neither has confidence (the existing 4 agents), current dedup behavior is unchanged.
|
|
42
|
+
|
|
43
|
+
## Compatibility
|
|
44
|
+
|
|
45
|
+
The legacy security agent uses string values (`'high' | 'medium' | 'low'`). New subagents use numeric anchors (`25 | 50 | 75 | 100`). The `ReviewFinding.confidence` field accepts either. Future migration of the security agent to numeric anchors is opt-in and out of scope here.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Risk keywords for depth calibration
|
|
2
|
+
|
|
3
|
+
> Used by Phase 3.5 CALIBRATE in `harness-code-review` to elevate a diff's depth tier when sensitive surfaces are touched. The list below is the **single source of truth** — Decisions 7 and 8 of the spec reference this file rather than re-enumerating. Modifications to this list are policy decisions; updates require PR review.
|
|
4
|
+
|
|
5
|
+
The calibrator matches against the changed-file content, file paths, and the commit message. Matching is case-insensitive and whole-word where possible (substring for path matches like `auth/` directories).
|
|
6
|
+
|
|
7
|
+
## Canonical list
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
auth
|
|
11
|
+
authn
|
|
12
|
+
authz
|
|
13
|
+
password
|
|
14
|
+
token
|
|
15
|
+
payment
|
|
16
|
+
billing
|
|
17
|
+
migration
|
|
18
|
+
migrate
|
|
19
|
+
external API
|
|
20
|
+
webhook
|
|
21
|
+
cryptography
|
|
22
|
+
crypto
|
|
23
|
+
session
|
|
24
|
+
cookie
|
|
25
|
+
personally identifiable
|
|
26
|
+
PII
|
|
27
|
+
compliance
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Tier rules (from spec Decision 8)
|
|
31
|
+
|
|
32
|
+
| Diff size | Keywords matched | Depth tier |
|
|
33
|
+
| --------: | ---------------: | ---------- |
|
|
34
|
+
| `< 50` | `0` | Quick |
|
|
35
|
+
| `50–199` | `0` | Standard |
|
|
36
|
+
| `< 50` | `1` | Standard |
|
|
37
|
+
| any | `≥ 2` | Deep |
|
|
38
|
+
| `≥ 200` | any | Deep |
|
|
39
|
+
|
|
40
|
+
Author override: `--depth quick|standard|deep` forces the tier and bypasses calibration.
|
|
@@ -42,6 +42,9 @@ cli:
|
|
|
42
42
|
- name: --thorough
|
|
43
43
|
description: Maximum rigor — always load learnings, full agent roster + meta-judge
|
|
44
44
|
required: false
|
|
45
|
+
- name: --depth
|
|
46
|
+
description: "Override Phase 3.5 depth calibration: quick|standard|deep. 'deep' activates all conditional subagents (adversarial, typescript-strict, frontend-races)."
|
|
47
|
+
required: false
|
|
45
48
|
- name: session-slug
|
|
46
49
|
description: Session slug for scoped state/handoff (passed by autopilot)
|
|
47
50
|
required: false
|
|
@@ -83,19 +83,22 @@ Read `docs/solutions/references/schema.yaml` for the authoritative track/categor
|
|
|
83
83
|
### Phase 5: WRITE (lock-protected)
|
|
84
84
|
|
|
85
85
|
1. Compute slug: kebab-case from the title; if a file with that slug already exists in the target directory, append `-2`, `-3`, etc.
|
|
86
|
-
2. **Acquire the per-category lock
|
|
87
|
-
- On `CompoundLockHeldError
|
|
86
|
+
2. **Acquire the per-category lock via the harness MCP server.** Call `acquire_compound_lock({ path: process.cwd(), category: '<category>' })`. On success it returns `{ acquired: true, token, lockPath }` — hold the `token` while you write the doc, then call `release_compound_lock({ token })` when finished. The MCP server holds the file handle and registers process-exit cleanup, so an abandoned agent does not leave a dangling lock-with-stale-PID. Lock path: `.harness/locks/compound-<category>.lock`. Fallback for environments without the MCP server (only works when `@harness-engineering/core` is resolvable from the project): `node -e "import('@harness-engineering/core').then(({ acquireCompoundLock }) => { const h = acquireCompoundLock('<category>'); /* write the doc here */ h.release(); })"`.
|
|
87
|
+
- On `{ acquired: false, error: 'CompoundLockHeldError', holderPid }` (or `CompoundLockHeldError` when invoked directly): report "compound lock for category `<category>` is held by pid `<holderPid>` — wait for it to release or run `/harness:compound` for a different category" and stop. **Do not retry automatically.** A second invocation on the same problem after release will go through Phase 3 and find the doc the first invocation produced.
|
|
88
88
|
3. Re-run a quick Phase 3 overlap-check inside the lock (defends against TOCTOU when the first overlap-check returned "no overlap" but another invocation completed in the meantime; the re-check is cheap).
|
|
89
89
|
4. Write the file at `docs/solutions/<track>/<category>/<slug>.md`.
|
|
90
90
|
5. Validate frontmatter against `SolutionDocFrontmatterSchema` by running `harness validate` (which runs `validateSolutionsDir`).
|
|
91
|
-
6. Release the lock.
|
|
91
|
+
6. Release the lock via `release_compound_lock({ token })` (or `handle.release()` on the fallback shell-out path).
|
|
92
92
|
7. Surface to chat: file path created (or updated), category, and a one-sentence summary.
|
|
93
93
|
|
|
94
94
|
## Harness Integration
|
|
95
95
|
|
|
96
96
|
- **`harness validate`** — Run after writing the doc; the solutions validator catches frontmatter errors before commit.
|
|
97
97
|
- **`harness check-deps`** — Not required (no new module imports introduced by writing a doc).
|
|
98
|
-
-
|
|
98
|
+
- **Harness MCP tools consumed by this skill** (canonical execution path — no project-local `@harness-engineering/core` required):
|
|
99
|
+
- `acquire_compound_lock({ path, category })` — returns `{ acquired: true, token, lockPath }` on success or `{ acquired: false, error: 'CompoundLockHeldError', holderPid, lockPath }` on contention.
|
|
100
|
+
- `release_compound_lock({ token })` — releases the lock; idempotent on repeat calls with the same token.
|
|
101
|
+
- **`@harness-engineering/core` lock primitive** (only directly relevant when the MCP server is unavailable) — `acquireCompoundLock(category, { cwd })` returns a release handle; throws `CompoundLockHeldError` on contention. See `packages/core/src/locks/compound-lock.ts`.
|
|
99
102
|
- **Schema authority** — `packages/core/src/solutions/schema.ts` is the single source of truth for tracks and categories. `docs/solutions/references/schema.yaml` mirrors it for human reading.
|
|
100
103
|
- **Boundary with `harness-knowledge-pipeline`** — Knowledge-pipeline extracts structural facts FROM CODE. Compound captures post-mortem playbooks WRITTEN AFTER A FIX. Compound's knowledge-track output is a _candidate input_ to the pipeline (Phase 7 of the spec wires this).
|
|
101
104
|
- **Boundary with `.harness/learnings.md`** — The file remains for ephemeral session notes. It is no longer the canonical sink for compounding knowledge — that's `docs/solutions/`.
|
|
@@ -56,7 +56,7 @@ When no arguments are provided (standalone invocation), discover plan from `docs
|
|
|
56
56
|
4. **Load session summary for cold start.** If resuming (session slug known):
|
|
57
57
|
- Call `listActiveSessions()` to read the session index.
|
|
58
58
|
- Call `loadSessionSummary()` for the target session.
|
|
59
|
-
- If ambiguous, present the index and ask which session to resume.
|
|
59
|
+
- If ambiguous, present the index and ask which session to resume. Ask in plain text — do not elevate this to `AskUserQuestion` (the session index can exceed its 4-option cap and a natural header like "Pick session" can exceed its 12-char cap, rendering the call as ERR).
|
|
60
60
|
|
|
61
61
|
5. **Check for known dead ends.** Review `learnings` tagged `[outcome:failure]`. Warn if any match current plan approaches.
|
|
62
62
|
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
## Process
|
|
15
15
|
|
|
16
|
+
**Prompt the human in plain text** — every choice and destructive confirmation in this skill (worktree location, discard-experiment, etc.) is plain text only. Do not elevate to `AskUserQuestion`: option labels like the A/B/C worktree-location choices and natural headers like "Discard commits" routinely exceed its 4-option / 12-char caps and render as ERR.
|
|
17
|
+
|
|
16
18
|
### Part A: Worktree Creation
|
|
17
19
|
|
|
18
20
|
#### Step 1: Choose Worktree Location
|
|
@@ -0,0 +1,279 @@
|
|
|
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
|
+
**Prompt the human in plain text** — every confirmation and selection in this skill (`Proceed? (y/n)`, post-critique selection, etc.) is plain text only. Do not elevate to `AskUserQuestion`: natural headers like "Confirm inputs" exceed its 12-char cap and option lists routinely exceed its 4-option cap, rendering the call as ERR.
|
|
19
|
+
|
|
20
|
+
### Iron Law
|
|
21
|
+
|
|
22
|
+
**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.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
### Phase 1: GROUND — Read STRATEGY.md and Confirm the Topic
|
|
27
|
+
|
|
28
|
+
1. **Resolve the focus argument.** If the user passed `--focus` (or supplied a one-line topic in the conversation), use it verbatim. Otherwise ask:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
What is the ideation topic? One short line (e.g., "onboarding for plugin-only users",
|
|
32
|
+
"lateral review depth", "pulse-report follow-up routing").
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Capture the answer; do not proceed without one.
|
|
36
|
+
|
|
37
|
+
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.
|
|
38
|
+
|
|
39
|
+
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.
|
|
40
|
+
|
|
41
|
+
Three cases:
|
|
42
|
+
- **`{ present: false }`:** print one line — `STRATEGY.md not present — ranking will use impact × confidence ÷ effort only; no strategy-alignment tiebreaker`. Continue.
|
|
43
|
+
- **`{ 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.
|
|
44
|
+
- **`{ 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.
|
|
45
|
+
|
|
46
|
+
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`.
|
|
47
|
+
|
|
48
|
+
4. **Confirm the topic.** Before generating, surface a 2-line summary:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
Topic: <focus>
|
|
52
|
+
Count: <N>
|
|
53
|
+
Strategy grounding: <enabled|disabled — reason>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Ask: `Proceed with these inputs? (y/n)`. Wait for confirmation.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
### Phase 2: GENERATE — Produce Candidate Ideas
|
|
61
|
+
|
|
62
|
+
Generate exactly N candidate ideas. Each idea is a structured object with the following fields:
|
|
63
|
+
|
|
64
|
+
| Field | Type | Description |
|
|
65
|
+
| ------------ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
66
|
+
| `premise` | string (1 sentence) | What this idea is, in one declarative sentence. Not aspirational — what the change IS, not what we hope it achieves. |
|
|
67
|
+
| `persona` | string (1 sentence) | Target persona segment (specific, not "developers"). If STRATEGY.md is present, prefer phrasing from its `Who it's for`. |
|
|
68
|
+
| `complexity` | `low \| medium \| high` | Rough engineering complexity estimate. |
|
|
69
|
+
| `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. |
|
|
70
|
+
| `impact` | `low \| medium \| high` | How much this matters if it works. Mapped to `1/2/3` for ranking. |
|
|
71
|
+
| `confidence` | `low \| medium \| high` | How confident we are that we can pull it off. Mapped to `1/2/3` for ranking. |
|
|
72
|
+
| `effort` | `low \| medium \| high` | Engineering effort to deliver. Mapped to `1/2/3` for ranking. |
|
|
73
|
+
|
|
74
|
+
**Generation rules:**
|
|
75
|
+
|
|
76
|
+
- **Spread the complexity surface.** Aim for at least one `low` and one `high` complexity idea; resist clustering everything as `medium`.
|
|
77
|
+
- **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.
|
|
78
|
+
- **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.
|
|
79
|
+
- **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.
|
|
80
|
+
|
|
81
|
+
Present the N candidates as a numbered list. Each line is 2-3 sentences max:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
1. [Premise]. Persona: [...]. Complexity: medium. Key risk: [...]. Impact/Confidence/Effort: M/M/L.
|
|
85
|
+
2. [Premise]. Persona: [...]. Complexity: low. Key risk: [...]. Impact/Confidence/Effort: H/L/L.
|
|
86
|
+
...
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
### Phase 3: CRITIQUE — Identify and Address Strongest Objections
|
|
92
|
+
|
|
93
|
+
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):
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
Idea 3: [Premise].
|
|
97
|
+
Strongest objection: [...]. Most likely failure mode: [...]. What would need to be true
|
|
98
|
+
for this objection to NOT hold: [...].
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
After all N critiques are presented, ask the user:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
Which objections do you want to answer (vs. accept as a downside)?
|
|
105
|
+
Options:
|
|
106
|
+
- all — I'll address every objection
|
|
107
|
+
- none — accept all critiques as known downsides
|
|
108
|
+
- <list of numbers, e.g., "1, 3, 7">
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
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).
|
|
112
|
+
|
|
113
|
+
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.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
### Phase 4: RANK — Score and Order
|
|
118
|
+
|
|
119
|
+
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]`.
|
|
120
|
+
|
|
121
|
+
**Strategy-alignment tiebreaker.** When `STRATEGY.md` was grounded in Phase 1, compute an alignment bonus per candidate:
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
alignment_bonus =
|
|
125
|
+
(premise plausibly advances a Tracks bullet ? 0.5 : 0)
|
|
126
|
+
+ (premise/persona references Target problem or Our approach ? 0.25 : 0)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
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).
|
|
130
|
+
|
|
131
|
+
Sort by final score descending. Stable on ties (preserve generation order so the user can find the original list).
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
### Phase 5: WRITE — Persist the Ranked Artifact
|
|
136
|
+
|
|
137
|
+
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`.
|
|
138
|
+
|
|
139
|
+
2. **Compute today's date** as `YYYY-MM-DD` (UTC).
|
|
140
|
+
|
|
141
|
+
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)`:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
docs/ideation/onboarding-for-plugin-only-use-2026-06-02.md # first run
|
|
145
|
+
docs/ideation/onboarding-for-plugin-only-use-2026-06-02-a3f9b2.md # collision
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
4. **Render the artifact.** Frontmatter + ranked list. See ranking math in `references/scoring.md`. Required fields:
|
|
149
|
+
|
|
150
|
+
```markdown
|
|
151
|
+
---
|
|
152
|
+
topic: <focus argument verbatim>
|
|
153
|
+
generated_at: <ISO 8601 timestamp>
|
|
154
|
+
strategy_grounded: <true | false>
|
|
155
|
+
strategy_path: <STRATEGY.md path if grounded, else null>
|
|
156
|
+
count_requested: <N>
|
|
157
|
+
count_generated: <N>
|
|
158
|
+
ranking_formula: '(impact × confidence) ÷ effort; strategy-alignment tiebreaker (max +0.75) applied only when |Δbase_score| ≤ 0.05'
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
# Ideation: <focus>
|
|
162
|
+
|
|
163
|
+
## Inputs
|
|
164
|
+
|
|
165
|
+
- Topic: <focus>
|
|
166
|
+
- Generated: <ISO timestamp>
|
|
167
|
+
- Strategy grounding: <enabled | disabled with one-line reason>
|
|
168
|
+
|
|
169
|
+
## Ranked candidates
|
|
170
|
+
|
|
171
|
+
### 1. <premise> — score: <final>
|
|
172
|
+
|
|
173
|
+
- Persona: <...>
|
|
174
|
+
- Complexity: <low|medium|high>
|
|
175
|
+
- Impact / Confidence / Effort: <H/M/L> — base score <X.XX>
|
|
176
|
+
- Strategy alignment: <none | +0.25 persona | +0.5 track:<name>> — final score <Y.YY>
|
|
177
|
+
- Strongest objection: <one paragraph>
|
|
178
|
+
- Objection answered: <yes/no — if yes, one paragraph rebuttal>
|
|
179
|
+
|
|
180
|
+
### 2. ...
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
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.
|
|
184
|
+
|
|
185
|
+
6. **Print the handoff.** Three lines:
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
Ideation artifact written: docs/ideation/<slug>-<date>.md
|
|
189
|
+
Top pick: <#1 premise> — score <Y.YY>
|
|
190
|
+
Next: invoke /harness:brainstorming <feature> to take a candidate into a spec, OR /harness:roadmap to enqueue picks for later.
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Harness Integration
|
|
196
|
+
|
|
197
|
+
- **Harness MCP tools consumed by this skill** (canonical execution path — no project-local `@harness-engineering/core` required):
|
|
198
|
+
- `read_strategy({ path })` — Phase 1 grounding oracle. Returns `{ present, valid, doc?, error? }` (the server runs `validateStrategy` + `parseStrategyDoc` + `asStrategyDoc` internally).
|
|
199
|
+
- **`@harness-engineering/core`** (only directly relevant when the MCP server is unavailable):
|
|
200
|
+
- `validateStrategy(cwd)`, `parseStrategyDoc(raw)` + `asStrategyDoc(parsed)`, `StrategyDocSchema`, `REQUIRED_STRATEGY_SECTIONS`.
|
|
201
|
+
- **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).
|
|
202
|
+
- **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.
|
|
203
|
+
- **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.
|
|
204
|
+
|
|
205
|
+
## Success Criteria
|
|
206
|
+
|
|
207
|
+
- Exactly one artifact is written per run, at `docs/ideation/<slug>-<YYYY-MM-DD>.md`. No spec, plan, ADR, or code is produced.
|
|
208
|
+
- The artifact contains exactly the number of candidates the user requested (after clamping to `[5, 25]`).
|
|
209
|
+
- Every candidate has all 7 fields populated (premise, persona, complexity, key_risk, impact, confidence, effort).
|
|
210
|
+
- Each candidate has a strongest-objection paragraph; objections the user elected to answer have a rebuttal paragraph.
|
|
211
|
+
- 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.
|
|
212
|
+
- When `STRATEGY.md` is absent or invalid, the skill completes without error and the artifact's frontmatter records `strategy_grounded: false`.
|
|
213
|
+
- 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)`.
|
|
214
|
+
- The artifact's frontmatter explicitly states the ranking formula so a future reader can reproduce the order.
|
|
215
|
+
|
|
216
|
+
## Examples
|
|
217
|
+
|
|
218
|
+
### Example: With STRATEGY.md (grounded, 10 candidates)
|
|
219
|
+
|
|
220
|
+
```
|
|
221
|
+
User: /harness:ideate --focus "pulse-report follow-up routing"
|
|
222
|
+
|
|
223
|
+
Phase 1:
|
|
224
|
+
Topic confirmed: "pulse-report follow-up routing"
|
|
225
|
+
Count: 10
|
|
226
|
+
STRATEGY.md detected — grounding enabled.
|
|
227
|
+
Tracks read: ["pulse-reports", "compound-engineering", "feedback-loops"]
|
|
228
|
+
Who-it's-for read: "engineering teams adopting harness"
|
|
229
|
+
|
|
230
|
+
Phase 2 (excerpt):
|
|
231
|
+
1. Auto-assign followups to the on-call rotation. Persona: on-call engineer.
|
|
232
|
+
Complexity: medium. Key risk: rotation data may be stale. I/C/E: H/M/M.
|
|
233
|
+
...
|
|
234
|
+
10. Email-digest weekly pulse for distributed teams. Persona: async-first eng.
|
|
235
|
+
Complexity: low. Key risk: duplicates Slack. I/C/E: M/L/L.
|
|
236
|
+
|
|
237
|
+
Phase 3:
|
|
238
|
+
User selects "answer 1, 4, 7"; provides three one-paragraph rebuttals.
|
|
239
|
+
|
|
240
|
+
Phase 4 (ranking, excerpt):
|
|
241
|
+
- Idea 1 base score: (H=3 × M=2) ÷ M=2 = 3.00
|
|
242
|
+
Idea 7 base score: 2.97 (|Δ| = 0.03 ≤ 0.05 — alignment window applies)
|
|
243
|
+
Idea 1 alignment: track match "pulse-reports" (+0.5) + persona match (+0.25) = +0.75 → final 3.75
|
|
244
|
+
Idea 7 alignment: track match "feedback-loops" (+0.5) → final 3.47
|
|
245
|
+
Idea 4 base score: 2.50 (|Δ vs idea 1| = 0.50 > 0.05 — alignment recorded but not applied)
|
|
246
|
+
|
|
247
|
+
Phase 5:
|
|
248
|
+
Write docs/ideation/pulse-report-follow-up-routin-2026-06-02.md
|
|
249
|
+
Top pick: "Auto-assign followups to the on-call rotation" — score 3.50
|
|
250
|
+
Next: invoke /harness:brainstorming "Pulse Followup Routing" to take this into a spec.
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Example: Without STRATEGY.md (no grounding, 5 candidates)
|
|
254
|
+
|
|
255
|
+
- Phase 1: `read_strategy` returns `{ present: false }`. Strategy grounding disabled; skill prints the one-line note and continues.
|
|
256
|
+
- Phase 2: 5 candidates generated. No track-alignment guidance applies; coverage of complexity surface remains a rule.
|
|
257
|
+
- Phase 4: ranking uses `(impact × confidence) ÷ effort` only. No tiebreaker bonus is added.
|
|
258
|
+
- Phase 5: artifact frontmatter has `strategy_grounded: false` and `strategy_path: null`. Handoff still routes the user to brainstorming.
|
|
259
|
+
|
|
260
|
+
### Example: Slug collision (same focus, same day)
|
|
261
|
+
|
|
262
|
+
- Run 1: writes `docs/ideation/onboarding-for-plugin-only-use-2026-06-02.md`.
|
|
263
|
+
- 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.
|
|
264
|
+
|
|
265
|
+
## Gates
|
|
266
|
+
|
|
267
|
+
- **One artifact per run, exactly.** A second write on the same run violates the Iron Law.
|
|
268
|
+
- **Never modify `STRATEGY.md`.** Even on present-but-invalid: surface the error and continue without grounding. Repair is `/harness:strategy`'s job.
|
|
269
|
+
- **Never derive a spec from ideate's artifact automatically.** Brainstorming is human-confirmed; ideate's output is an INPUT to brainstorming, not a replacement.
|
|
270
|
+
- **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.
|
|
271
|
+
- **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.
|
|
272
|
+
|
|
273
|
+
## Escalation
|
|
274
|
+
|
|
275
|
+
- **User wants the artifact converted to a spec automatically.** Refuse; cite the Iron Law. Offer `/harness:brainstorming "<top-pick title>"` as the next step.
|
|
276
|
+
- **STRATEGY.md is present but invalid.** Print the validation error verbatim; do not block. Suggest `/harness:strategy` and continue with `strategy_grounded: false`.
|
|
277
|
+
- **User insists on `N > 25`.** Clamp to 25 and inform; offer to chain a second run with a different focus argument.
|
|
278
|
+
- **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.
|
|
279
|
+
- **Output directory cannot be created.** Surface the filesystem error verbatim. Do not silently write to a fallback path.
|