@harness-engineering/cli 2.7.1 → 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.
Files changed (139) hide show
  1. package/dist/agents/personas/adversarial-reviewer.yaml +43 -0
  2. package/dist/agents/personas/frontend-races-reviewer.yaml +54 -0
  3. package/dist/agents/personas/typescript-strict-reviewer.yaml +53 -0
  4. package/dist/agents/skills/CHANGELOG.md +12 -0
  5. package/dist/agents/skills/claude-code/align-design-system/SKILL.md +18 -0
  6. package/dist/agents/skills/claude-code/align-design-system/skill.yaml +3 -0
  7. package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +37 -5
  8. package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +107 -22
  9. package/dist/agents/skills/claude-code/harness-code-review/references/confidence-rubric.md +45 -0
  10. package/dist/agents/skills/claude-code/harness-code-review/references/risk-keywords.md +40 -0
  11. package/dist/agents/skills/claude-code/harness-code-review/skill.yaml +3 -0
  12. package/dist/agents/skills/claude-code/harness-compound/SKILL.md +7 -4
  13. package/dist/agents/skills/claude-code/harness-ideate/SKILL.md +277 -0
  14. package/dist/agents/skills/claude-code/harness-ideate/references/scoring.md +88 -0
  15. package/dist/agents/skills/claude-code/harness-ideate/skill.yaml +66 -0
  16. package/dist/agents/skills/claude-code/harness-planning/SKILL.md +14 -4
  17. package/dist/agents/skills/claude-code/harness-pulse/SKILL.md +12 -16
  18. package/dist/agents/skills/claude-code/harness-roadmap-pilot/SKILL.md +34 -6
  19. package/dist/agents/skills/claude-code/harness-strategy/SKILL.md +152 -0
  20. package/dist/agents/skills/claude-code/harness-strategy/references/interview.md +122 -0
  21. package/dist/agents/skills/claude-code/harness-strategy/skill.yaml +54 -0
  22. package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +76 -10
  23. package/dist/agents/skills/codex/align-design-system/SKILL.md +18 -0
  24. package/dist/agents/skills/codex/align-design-system/skill.yaml +3 -0
  25. package/dist/agents/skills/codex/harness-brainstorming/SKILL.md +37 -5
  26. package/dist/agents/skills/codex/harness-code-review/SKILL.md +107 -22
  27. package/dist/agents/skills/codex/harness-code-review/references/confidence-rubric.md +45 -0
  28. package/dist/agents/skills/codex/harness-code-review/references/risk-keywords.md +40 -0
  29. package/dist/agents/skills/codex/harness-code-review/skill.yaml +3 -0
  30. package/dist/agents/skills/codex/harness-compound/SKILL.md +7 -4
  31. package/dist/agents/skills/codex/harness-ideate/SKILL.md +277 -0
  32. package/dist/agents/skills/codex/harness-ideate/references/scoring.md +88 -0
  33. package/dist/agents/skills/codex/harness-ideate/skill.yaml +66 -0
  34. package/dist/agents/skills/codex/harness-planning/SKILL.md +14 -4
  35. package/dist/agents/skills/codex/harness-pulse/SKILL.md +12 -16
  36. package/dist/agents/skills/codex/harness-roadmap-pilot/SKILL.md +34 -6
  37. package/dist/agents/skills/codex/harness-strategy/SKILL.md +152 -0
  38. package/dist/agents/skills/codex/harness-strategy/references/interview.md +122 -0
  39. package/dist/agents/skills/codex/harness-strategy/skill.yaml +54 -0
  40. package/dist/agents/skills/codex/initialize-harness-project/SKILL.md +76 -10
  41. package/dist/agents/skills/cursor/align-design-system/SKILL.md +18 -0
  42. package/dist/agents/skills/cursor/align-design-system/skill.yaml +3 -0
  43. package/dist/agents/skills/cursor/harness-brainstorming/SKILL.md +37 -5
  44. package/dist/agents/skills/cursor/harness-code-review/SKILL.md +107 -22
  45. package/dist/agents/skills/cursor/harness-code-review/references/confidence-rubric.md +45 -0
  46. package/dist/agents/skills/cursor/harness-code-review/references/risk-keywords.md +40 -0
  47. package/dist/agents/skills/cursor/harness-code-review/skill.yaml +3 -0
  48. package/dist/agents/skills/cursor/harness-compound/SKILL.md +7 -4
  49. package/dist/agents/skills/cursor/harness-ideate/SKILL.md +277 -0
  50. package/dist/agents/skills/cursor/harness-ideate/references/scoring.md +88 -0
  51. package/dist/agents/skills/cursor/harness-ideate/skill.yaml +66 -0
  52. package/dist/agents/skills/cursor/harness-planning/SKILL.md +14 -4
  53. package/dist/agents/skills/cursor/harness-pulse/SKILL.md +12 -16
  54. package/dist/agents/skills/cursor/harness-roadmap-pilot/SKILL.md +34 -6
  55. package/dist/agents/skills/cursor/harness-strategy/SKILL.md +152 -0
  56. package/dist/agents/skills/cursor/harness-strategy/references/interview.md +122 -0
  57. package/dist/agents/skills/cursor/harness-strategy/skill.yaml +54 -0
  58. package/dist/agents/skills/cursor/initialize-harness-project/SKILL.md +76 -10
  59. package/dist/agents/skills/gemini-cli/align-design-system/SKILL.md +18 -0
  60. package/dist/agents/skills/gemini-cli/align-design-system/skill.yaml +3 -0
  61. package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +37 -5
  62. package/dist/agents/skills/gemini-cli/harness-code-review/SKILL.md +107 -22
  63. package/dist/agents/skills/gemini-cli/harness-code-review/references/confidence-rubric.md +45 -0
  64. package/dist/agents/skills/gemini-cli/harness-code-review/references/risk-keywords.md +40 -0
  65. package/dist/agents/skills/gemini-cli/harness-code-review/skill.yaml +3 -0
  66. package/dist/agents/skills/gemini-cli/harness-compound/SKILL.md +7 -4
  67. package/dist/agents/skills/gemini-cli/harness-ideate/SKILL.md +277 -0
  68. package/dist/agents/skills/gemini-cli/harness-ideate/references/scoring.md +88 -0
  69. package/dist/agents/skills/gemini-cli/harness-ideate/skill.yaml +66 -0
  70. package/dist/agents/skills/gemini-cli/harness-planning/SKILL.md +14 -4
  71. package/dist/agents/skills/gemini-cli/harness-pulse/SKILL.md +12 -16
  72. package/dist/agents/skills/gemini-cli/harness-roadmap-pilot/SKILL.md +34 -6
  73. package/dist/agents/skills/gemini-cli/harness-strategy/SKILL.md +152 -0
  74. package/dist/agents/skills/gemini-cli/harness-strategy/references/interview.md +122 -0
  75. package/dist/agents/skills/gemini-cli/harness-strategy/skill.yaml +54 -0
  76. package/dist/agents/skills/gemini-cli/initialize-harness-project/SKILL.md +76 -10
  77. package/dist/agents/skills/package.json +1 -1
  78. package/dist/agents/skills/tests/harness-strategy.test.ts +145 -0
  79. package/dist/agents-md-WMJO5HSM.js +13 -0
  80. package/dist/analyzer-V633GUHY-MBCQWKDU.js +26 -0
  81. package/dist/{architecture-LUR2I67H.js → architecture-EVYVGPRZ.js} +6 -6
  82. package/dist/{assess-project-OJWECOP2.js → assess-project-KZG563SO.js} +1 -1
  83. package/dist/bin/harness-mcp.js +17 -17
  84. package/dist/bin/harness.js +27 -27
  85. package/dist/{check-phase-gate-HS5KYLRO.js → check-phase-gate-MK364VXS.js} +6 -6
  86. package/dist/{chunk-6UHDQP2N.js → chunk-2N4OENGE.js} +1 -1
  87. package/dist/{chunk-FC4JPM6W.js → chunk-2SNRCAC3.js} +3 -3
  88. package/dist/{chunk-LGYXR2KZ.js → chunk-4BDOSCNY.js} +137 -71
  89. package/dist/{chunk-N5NSSLMU.js → chunk-5XL5QJ5B.js} +2 -2
  90. package/dist/{chunk-LECXPXS3.js → chunk-7EQAZKJ5.js} +2 -2
  91. package/dist/{chunk-LYIPI2SJ.js → chunk-ACOOG3UW.js} +6 -6
  92. package/dist/{chunk-FXZI6NJ2.js → chunk-B7KMTHN3.js} +51 -4
  93. package/dist/{chunk-OH3NXXUY.js → chunk-BDGTZRZ6.js} +11 -1
  94. package/dist/{chunk-NIVWM7OW.js → chunk-C7J55C6E.js} +10 -10
  95. package/dist/{chunk-7PLIWP7U.js → chunk-CAQPSFPT.js} +4042 -738
  96. package/dist/{chunk-TIH53QXY.js → chunk-CLI4K2CH.js} +1 -1
  97. package/dist/{chunk-INBTDBV2.js → chunk-EEFRPEWT.js} +1 -1
  98. package/dist/{chunk-VI4IS55S.js → chunk-FZ5MBXEG.js} +6 -6
  99. package/dist/{chunk-WZY5U6NS.js → chunk-GOHWCHCS.js} +1809 -812
  100. package/dist/{chunk-VSIRUZQP.js → chunk-HRSE6IQD.js} +2 -2
  101. package/dist/{chunk-CZPOPMMI.js → chunk-KBCPELBC.js} +3 -3
  102. package/dist/{chunk-7AF6C5GE.js → chunk-KI6PHH6Q.js} +3 -3
  103. package/dist/{chunk-KN3EMDZ5.js → chunk-LADPYELQ.js} +23 -3
  104. package/dist/{chunk-Y4T6ENKQ.js → chunk-N55WOGN3.js} +86 -17
  105. package/dist/{chunk-H2ZJOJ7A.js → chunk-PP6ZRL5T.js} +316 -42
  106. package/dist/{chunk-RJ2WEES5.js → chunk-STESM73J.js} +2 -2
  107. package/dist/{chunk-B2VAYLYI.js → chunk-UBZQE3JN.js} +2 -2
  108. package/dist/{chunk-GGSNWH7P.js → chunk-UJFNIWC7.js} +5 -5
  109. package/dist/{chunk-FEKBXX2J.js → chunk-UUO4K7NX.js} +9 -9
  110. package/dist/{chunk-Z3TMCCZB.js → chunk-UXPWSV3B.js} +9 -9
  111. package/dist/{chunk-O2ASYKA6.js → chunk-VBNJAKUH.js} +2 -2
  112. package/dist/{chunk-PTHX545Q.js → chunk-X4EFYVCZ.js} +2 -2
  113. package/dist/{ci-workflow-MDSTHJOY.js → ci-workflow-IW2H5DC4.js} +5 -5
  114. package/dist/{dist-E3SAAHCM.js → dist-ICW4QUEW.js} +5 -1
  115. package/dist/{dist-72ID44UE.js → dist-JCFK263L.js} +52 -4
  116. package/dist/{dist-R3TOOPJ7.js → dist-OWHMNL4W.js} +1 -1
  117. package/dist/{docs-2RFOJ6XY.js → docs-7CP6VV42.js} +6 -6
  118. package/dist/engine-MKJEBWU7.js +13 -0
  119. package/dist/{entropy-3UX6644G.js → entropy-6JOZJYG7.js} +5 -5
  120. package/dist/{feedback-CVCFYND4.js → feedback-T65AEJEG.js} +1 -1
  121. package/dist/{generate-agent-definitions-HZ3XENWO.js → generate-agent-definitions-4VI4YTO2.js} +6 -6
  122. package/dist/{glob-helper-EX4YZKZO.js → glob-helper-GLZAURJC.js} +1 -1
  123. package/dist/{graph-loader-EIFEOUVI.js → graph-loader-HHXN5FLP.js} +1 -1
  124. package/dist/index.d.ts +202 -0
  125. package/dist/index.js +27 -27
  126. package/dist/{loader-6RHWU5FH.js → loader-AWTHHE3A.js} +5 -5
  127. package/dist/{mcp-OYR26JDI.js → mcp-JBIBINO2.js} +17 -17
  128. package/dist/{performance-JJMIRXCH.js → performance-NCOUDOMW.js} +6 -6
  129. package/dist/{review-pipeline-BHQZIXWZ.js → review-pipeline-YIC6JPMY.js} +5 -5
  130. package/dist/{runtime-DALTAVTN.js → runtime-5MHV4UEE.js} +5 -5
  131. package/dist/{scan-LYKLM4EQ.js → scan-P7YFKB77.js} +1 -1
  132. package/dist/{security-RMLMYFPB.js → security-VZPJNIDP.js} +1 -1
  133. package/dist/{validate-R7DZRDFK.js → validate-7BE4VTFI.js} +6 -6
  134. package/dist/validate-cross-check-F7GEBRDH.js +13 -0
  135. package/package.json +7 -7
  136. package/dist/agents-md-FKMKH6ZF.js +0 -13
  137. package/dist/analyzer-H3AHBFSL-KPOPJYRB.js +0 -26
  138. package/dist/engine-BSFKOGPN.js +0 -13
  139. package/dist/validate-cross-check-AUUZFNVL.js +0 -13
@@ -35,7 +35,26 @@ When no arguments are provided (standalone invocation), the skill operates exact
35
35
 
36
36
  ### Phase 1: EXPLORE -- Gather Context
37
37
 
38
- 1. **Load project context.** Call `gather_context({ path: "<project-root>", intent: "<feature description>", skill: "harness-brainstorming", session: "<session-slug-if-known>", include: ["graph", "businessKnowledge", "sessions", "validation"] })`. The `graph` context surfaces `business_fact` nodes relevant to the feature domain. The `businessKnowledge` context loads documented domain knowledge from `docs/knowledge/`. Use both to ground exploration in verified facts rather than assumptions.
38
+ 0a. **Read STRATEGY.md if present at repo root (upstream grounding).** Strategy is the durable product anchor that ranks above feature-level context — read it first so the rest of EXPLORE can cross-reference. Call `read_strategy({ path: "<project-root>" })` 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.
39
+
40
+ Fallback for environments without the MCP server (only works when core is resolvable from the project):
41
+
42
+ ```bash
43
+ node -e "import('@harness-engineering/core').then(async m => {
44
+ const v = await m.validateStrategy(process.cwd());
45
+ if (!v.ok || !v.value.present) { console.log(JSON.stringify({ grounded: false, reason: 'absent' })); return; }
46
+ const raw = require('fs').readFileSync('STRATEGY.md', 'utf-8');
47
+ console.log(JSON.stringify({ grounded: true, doc: m.asStrategyDoc(m.parseStrategyDoc(raw)) }));
48
+ })"
49
+ ```
50
+
51
+ Three cases:
52
+
53
+ - **Absent or invalid:** soft-fail silently. Do not block and do not warn in the spec — the skill works exactly as before when there is no strategic anchor.
54
+ - **Present and valid:** capture the `Target problem`, `Our approach`, `Who it's for`, and `Tracks` section bodies. Treat them as grounding context alongside `gather_context` outputs. The captured strategy is cited as evidence in step 1's `[evidence]` annotations of the spec output.
55
+ - **Contradiction with the user's feature description:** do NOT auto-resolve. Carry the contradiction forward as an open question into Phase 2 EVALUATE — surface it explicitly so the human can decide whether to refine the feature or update strategy via `/harness:strategy`.
56
+
57
+ 1. **Load project context.** Call `gather_context({ path: "<project-root>", intent: "<feature description>", skill: "harness-brainstorming", session: "<session-slug-if-known>", include: ["graph", "businessKnowledge", "sessions", "validation"] })`. The `graph` context surfaces `business_fact` nodes relevant to the feature domain. The `businessKnowledge` context loads documented domain knowledge from `docs/knowledge/`. Use both to ground exploration in verified facts rather than assumptions. When `STRATEGY.md` was loaded in step 0a, treat its sections as a higher-tier grounding source than `businessKnowledge` — strategy reflects an explicit human commitment, knowledge is observation.
39
58
  2. **Read the existing codebase.** Understand architecture, constraints, and conventions. Check AGENTS.md, existing specs in `docs/`, and relevant source files.
40
59
  3. **Identify the problem boundary.** What exactly needs solving? What is out of scope? Write both down. Cross-reference `businessKnowledge` domains — if documented business rules constrain the problem, note them.
41
60
  4. **Check for prior art.** Has this been partially solved elsewhere? Are there patterns to follow or deliberately break?
@@ -66,7 +85,8 @@ When no arguments are provided (standalone invocation), the skill operates exact
66
85
  2. **Prefer multiple choice over open-ended questions.** Give 2-4 concrete options with brief tradeoff notes.
67
86
  3. **Acknowledge answers and build on them.** Do not re-ask clarified points. Track decisions as they accumulate.
68
87
  4. **Apply YAGNI ruthlessly.** For every proposed capability, ask: "Do we need this for the stated goal, or is this speculative?" If speculative, cut it. If the human insists, note it as a future consideration.
69
- 5. **Continue until you have enough clarity** to propose concrete approaches. Typically 3-7 questions suffice. If you need >10, the scope is too large -- decompose.
88
+ 5. **Surface strategy contradictions.** If Phase 1 step 0a captured a contradiction between the feature description and `STRATEGY.md`, ask the human about it explicitly as one of the first few EVALUATE questions. Frame it as a choice — refine the feature to align, or refine strategy via `/harness:strategy` — never auto-resolve. Skip this when STRATEGY.md was absent or no contradiction was detected.
89
+ 6. **Continue until you have enough clarity** to propose concrete approaches. Typically 3-7 questions suffice. If you need >10, the scope is too large -- decompose.
70
90
 
71
91
  ### Context Keywords
72
92
 
@@ -166,14 +186,23 @@ These flow into `handoff.json` `contextKeywords` field. Select keywords that hel
166
186
 
167
187
  The human must explicitly approve before this skill is complete.
168
188
 
169
- 7. **Add feature to roadmap.** If `docs/roadmap.md` exists:
189
+ 7. **Commit spec artifacts.** After approval, commit the spec and skill recommendations so the paper trail enters git history at sign-off rather than retroactively:
190
+
191
+ ```bash
192
+ git add docs/changes/<feature>/proposal.md docs/changes/<feature>/SKILLS.md
193
+ git commit -m "docs(<feature>): add spec"
194
+ ```
195
+
196
+ Do not skip this step. `harness-execution` commits only implementation files, so a spec uncommitted here stays untracked until someone notices. If a pre-commit hook reformats either file, re-add and re-commit.
197
+
198
+ 8. **Add feature to roadmap.** If `docs/roadmap.md` exists:
170
199
  - Derive feature name from the spec title (the H1 heading).
171
200
  - Call `manage_roadmap` with action `add`, `status: "planned"`, `milestone: "Current Work"`, and the spec path.
172
201
  - If the feature already exists, skip silently.
173
202
  - If `manage_roadmap` is unavailable, fall back to `parseRoadmap`/`serializeRoadmap` from core. Warn: "External sync skipped (MCP unavailable). Run `manage_roadmap sync` when MCP is restored."
174
203
  - If no roadmap exists, skip silently.
175
204
 
176
- 8. **Write handoff and suggest transition.** After approval:
205
+ 9. **Write handoff and suggest transition.** After approval:
177
206
 
178
207
  Write handoff to the session-scoped path when a session slug is known, otherwise fall back to the global path:
179
208
  - Session-scoped (preferred): `.harness/sessions/<session-slug>/handoff.json`
@@ -292,7 +321,8 @@ Technical claims about existing code, architecture, or tradeoffs MUST cite evide
292
321
  1. **File reference:** `file:line` (e.g., `src/services/auth.ts:42` -- "existing JWT middleware")
293
322
  2. **Prior art:** `file` with description (e.g., `src/utils/email.ts` -- "reusable for notifications")
294
323
  3. **Docs:** `docs/path` (e.g., `docs/changes/user-auth/proposal.md` -- "established OAuth2 standard")
295
- 4. **Session evidence:** Write via `manage_state` `append_entry` to `evidence` section.
324
+ 4. **Strategy grounding:** `STRATEGY.md` with section reference (e.g., `STRATEGY.md#tracks` -- "advances the 'pulse-reports' track"). Cite when Phase 1 step 0a loaded a valid strategy AND the decision is informed by it. Mandatory when the spec extends, narrows, or contradicts a strategy section.
325
+ 5. **Session evidence:** Write via `manage_state` `append_entry` to `evidence` section.
296
326
 
297
327
  **When to cite:** Phase 1 (existing code/patterns), Phase 3 (tradeoff justifications), Phase 4 (spec referencing existing implementation).
298
328
 
@@ -302,9 +332,11 @@ Technical claims about existing code, architecture, or tradeoffs MUST cite evide
302
332
 
303
333
  - **`harness validate`** -- Run after writing the spec. Verifies project health and spec placement.
304
334
  - **`harness check-docs`** -- Verify spec does not conflict with existing docs.
335
+ - **`STRATEGY.md` grounding (Phase 1 step 0a)** -- When present at repo root and valid, loaded via the `read_strategy` MCP tool (which the harness MCP server backs with `validateStrategy` + `parseStrategyDoc` + `asStrategyDoc` from `@harness-engineering/core` — projects do not need core installed). Soft-fails when absent or invalid; cites strategy sections in the spec's evidence annotations when present. Boundary with `harness-strategy`: brainstorming READS; `harness-strategy` WRITES. Never modify `STRATEGY.md` from this skill.
305
336
  - **Spec location** -- `docs/changes/<feature>/proposal.md`.
306
337
  - **Handoff** -- Once approved, invoke harness-planning to create the implementation plan.
307
338
  - **Session directory** — When session slug is known, handoff goes to `.harness/sessions/<slug>/handoff.json`. The session directory structure is: `handoff.json`, `state.json`, `artifacts.json` (registry of spec/plan paths and file lists). Do not write to `.harness/handoff.json` in session context.
339
+ - **Spec commit** -- After sign-off (Phase 4 Step 7), commit `docs/changes/<feature>/proposal.md` and `docs/changes/<feature>/SKILLS.md` so the spec enters git history at approval, not retroactively. `harness-execution` does not backfill these — see issue #487.
308
340
  - **Roadmap sync** -- After approval, call `manage_roadmap` action `add` to register as `planned`. Skip silently if no roadmap. Duplicates ignored.
309
341
  - **`emit_interaction`** -- End of Phase 4 to suggest transition to harness-planning (confirmed transition).
310
342
 
@@ -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 4: FAN-OUT
37
- |
38
- Phase 7: OUTPUT <-- Phase 6: DEDUP+MERGE <-- Phase 5: VALIDATE <------+
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 | Exit Condition |
42
- | -------------- | ----- | -------------------------------- | ------------------------------------------------- |
43
- | 1. GATE | fast | Skip ineligible PRs (CI only) | PR eligible, or exit with reason |
44
- | 2. MECHANICAL | none | Lint, typecheck, test, sec scan | All pass -> continue; any fail -> report and stop |
45
- | 3. CONTEXT | fast | Scope context per review domain | Context bundles assembled for each subagent |
46
- | 4. FAN-OUT | mixed | Parallel review subagents | All subagents return ReviewFinding[] |
47
- | 5. VALIDATE | none | Exclude mechanical dupes, verify | Unvalidated findings discarded |
48
- | 6. DEDUP+MERGE | none | Group, merge, assign severity | Deduplicated finding list with merged evidence |
49
- | 7. OUTPUT | none | Text output or GitHub comments | Review delivered, exit code set |
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 4.
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
- **Exit:** All four agents returned findings. Continue to Phase 5.
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 by shelling out.** Run a Node one-liner that imports `acquireCompoundLock` from `@harness-engineering/core`, holds the handle while you write the doc, then releases it. Example: `node -e "import('@harness-engineering/core').then(({ acquireCompoundLock }) => { const h = acquireCompoundLock('<category>'); /* write the doc here */ h.release(); }).catch(err => { console.error(err.message); process.exit(1); })"`. Lock path: `.harness/locks/compound-<category>.lock`. The MCP tool `acquire_compound_lock` is planned for a later phase — **do not attempt to call it yet**; the shell-out is the only supported path right now.
87
- - On `CompoundLockHeldError`: report "compound lock for category `<category>` is held by pid `<N>` — 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.
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
- - **`@harness-engineering/core` lock primitive** `acquireCompoundLock(category, { cwd })` returns a release handle; throws `CompoundLockHeldError` on contention. See `packages/core/src/locks/compound-lock.ts`.
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/`.