@harness-engineering/cli 4.0.0 → 4.1.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 (79) hide show
  1. package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +9 -8
  2. package/dist/agents/skills/claude-code/pre-merge-brief/SKILL.md +86 -0
  3. package/dist/agents/skills/claude-code/pre-merge-brief/skill.yaml +67 -0
  4. package/dist/agents/skills/claude-code/product-advisor/SKILL.md +202 -0
  5. package/dist/agents/skills/claude-code/product-advisor/skill.yaml +74 -0
  6. package/dist/agents/skills/codex/harness-autopilot/SKILL.md +9 -8
  7. package/dist/agents/skills/codex/pre-merge-brief/SKILL.md +86 -0
  8. package/dist/agents/skills/codex/pre-merge-brief/skill.yaml +67 -0
  9. package/dist/agents/skills/codex/product-advisor/SKILL.md +202 -0
  10. package/dist/agents/skills/codex/product-advisor/skill.yaml +74 -0
  11. package/dist/agents/skills/cursor/harness-autopilot/SKILL.md +9 -8
  12. package/dist/agents/skills/cursor/pre-merge-brief/SKILL.md +86 -0
  13. package/dist/agents/skills/cursor/pre-merge-brief/skill.yaml +67 -0
  14. package/dist/agents/skills/cursor/product-advisor/SKILL.md +202 -0
  15. package/dist/agents/skills/cursor/product-advisor/skill.yaml +74 -0
  16. package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +9 -8
  17. package/dist/agents/skills/gemini-cli/pre-merge-brief/SKILL.md +86 -0
  18. package/dist/agents/skills/gemini-cli/pre-merge-brief/skill.yaml +67 -0
  19. package/dist/agents/skills/gemini-cli/product-advisor/SKILL.md +202 -0
  20. package/dist/agents/skills/gemini-cli/product-advisor/skill.yaml +74 -0
  21. package/dist/{agents-md-7OSNWU52.js → agents-md-7L4PKKOM.js} +4 -4
  22. package/dist/analyzer-XRCV63KC-HLTEIKAJ.js +26 -0
  23. package/dist/{architecture-2XYGJGT3.js → architecture-RCHFDI7E.js} +5 -5
  24. package/dist/{assess-project-3KPP2D6M.js → assess-project-YUDPNRS6.js} +5 -3
  25. package/dist/bin/harness-mcp.js +16 -16
  26. package/dist/bin/harness.js +27 -27
  27. package/dist/{check-phase-gate-46U5AAXE.js → check-phase-gate-56GS3A72.js} +5 -5
  28. package/dist/{chunk-MSBJ445U.js → chunk-4SKWGVYD.js} +5 -5
  29. package/dist/{chunk-CLI4K2CH.js → chunk-4U5LDFCY.js} +1 -1
  30. package/dist/{chunk-6YXCZV33.js → chunk-ABRYIEWJ.js} +1090 -714
  31. package/dist/{chunk-AK67S3O4.js → chunk-AU4YPEIE.js} +3 -3
  32. package/dist/{chunk-BV45354Q.js → chunk-DGVT4DBI.js} +9 -9
  33. package/dist/{chunk-363V6GPR.js → chunk-GLHLXTKC.js} +9 -9
  34. package/dist/{chunk-VTUINXWR.js → chunk-GSYBGOY3.js} +1 -1
  35. package/dist/{chunk-FZ4Q73HA.js → chunk-IGWJRAJT.js} +1 -1
  36. package/dist/{chunk-S2RQPPL6.js → chunk-N4AI2WFH.js} +1 -1
  37. package/dist/{chunk-HXMAIVV2.js → chunk-NCMJXBEO.js} +1 -1
  38. package/dist/{chunk-ZEYAOYJL.js → chunk-OZSKLJQW.js} +1 -1
  39. package/dist/{chunk-VTU3QOJT.js → chunk-P4NA5OQX.js} +1 -1
  40. package/dist/{chunk-WL3O2PKJ.js → chunk-RY2U77OY.js} +8 -8
  41. package/dist/{chunk-TTWNGOBT.js → chunk-RZQZXWEL.js} +32 -7
  42. package/dist/{chunk-KLPX55TI.js → chunk-UACYZCW4.js} +239 -146
  43. package/dist/{chunk-IYWT3JJW.js → chunk-VG4G3R2V.js} +1 -1
  44. package/dist/{chunk-PP6ZRL5T.js → chunk-WZJR6SOI.js} +536 -422
  45. package/dist/{chunk-PHX45JYN.js → chunk-XW5XVVMI.js} +2 -2
  46. package/dist/{chunk-MYVTYFQD.js → chunk-XZNCONFG.js} +1 -1
  47. package/dist/{chunk-GXCPDAS5.js → chunk-Y33P35U3.js} +26 -8
  48. package/dist/{chunk-XFHZ7GCI.js → chunk-Y5HPJMTM.js} +19 -3
  49. package/dist/{chunk-N55WOGN3.js → chunk-YJYUJSWK.js} +59 -21
  50. package/dist/{chunk-SPE7P4GL.js → chunk-YWRPQZL7.js} +1 -1
  51. package/dist/{chunk-6NCREWWM.js → chunk-YXOPQEFZ.js} +3 -3
  52. package/dist/{chunk-2N4OENGE.js → chunk-YYFSFSB3.js} +1 -1
  53. package/dist/{chunk-ERILXQBP.js → chunk-Z4XWWNYX.js} +615 -433
  54. package/dist/{chunk-HMW3C5DP.js → chunk-ZU6T7W3U.js} +2 -2
  55. package/dist/{ci-workflow-XJN4UO3Q.js → ci-workflow-TFAA5BK7.js} +4 -4
  56. package/dist/{dist-OWHMNL4W.js → dist-DWBTZXR5.js} +1 -1
  57. package/dist/{dist-IPVFYGY2.js → dist-MCTEX5QH.js} +5 -3
  58. package/dist/{docs-RSFZTNPG.js → docs-BBMAN3CY.js} +5 -5
  59. package/dist/{engine-DJIHY4JT.js → engine-R2YH74AL.js} +4 -4
  60. package/dist/{entropy-EAEKJKRM.js → entropy-5UP5N6AF.js} +7 -4
  61. package/dist/{feedback-JT5X3DBC.js → feedback-6MDCCFZL.js} +1 -1
  62. package/dist/{generate-agent-definitions-CC6KED3E.js → generate-agent-definitions-KKAN5DB5.js} +5 -5
  63. package/dist/{glob-helper-GLZAURJC.js → glob-helper-VR6UCZZB.js} +1 -1
  64. package/dist/{graph-loader-HHXN5FLP.js → graph-loader-STFGYKZH.js} +1 -1
  65. package/dist/hooks/sentinel-pre.js +15 -138
  66. package/dist/index.d.ts +61 -0
  67. package/dist/index.js +27 -27
  68. package/dist/{loader-UWNVTYBY.js → loader-2WT2ZE2T.js} +4 -4
  69. package/dist/{mcp-TCLNK7HG.js → mcp-5V4LPMB3.js} +16 -16
  70. package/dist/{performance-R6O3N3UB.js → performance-2N3CFXLR.js} +5 -5
  71. package/dist/{review-pipeline-MOOWXWSQ.js → review-pipeline-XZIGBU3Q.js} +4 -4
  72. package/dist/{runtime-RIWQUKBQ.js → runtime-POME3GTR.js} +4 -4
  73. package/dist/{scan-P7YFKB77.js → scan-IYSVRPD2.js} +1 -1
  74. package/dist/{security-U76C54W6.js → security-QLJLMSIW.js} +1 -1
  75. package/dist/{state-events-F44CUUZG.js → state-events-YY5KBZTC.js} +4 -4
  76. package/dist/{validate-IUAV7MOU.js → validate-VZORVK43.js} +5 -5
  77. package/dist/{validate-cross-check-M2ZM6RFY.js → validate-cross-check-OYKEDCST.js} +4 -4
  78. package/package.json +5 -4
  79. package/dist/analyzer-V633GUHY-MBCQWKDU.js +0 -26
@@ -0,0 +1,202 @@
1
+ # Product Advisor
2
+
3
+ > Turn a client diagram + conversation into a Business Requirements Document and a resolved gap-list, then seed the harness pipeline. The pre-inception front door: gather requirements with AI, feed them in, and let the existing flow continue as it does today.
4
+
5
+ ## When to Use
6
+
7
+ - At the **inception** of a client engagement, when a solution architect / pre-sales engineer has a rough idea, a diagram, and conversation notes but no structured requirements yet.
8
+ - When you want to turn "a diagram and some notes" into a client-legible BRD plus an explicit list of what is still unknown.
9
+ - When the output should **seed the roadmap** (many work items) and ground the engagement's strategy — not produce a single spec.
10
+ - NOT for authoring a spec/proposal — that is `harness-brainstorming`'s job. Product Advisor stops at BRD + roadmap seeding.
11
+ - NOT for writing or updating `STRATEGY.md` directly — that is `harness-strategy`'s job. This skill only reads strategy and _offers_ to seed it.
12
+ - NOT for internal feature work where the requirements already live in the codebase or an existing spec — go straight to `harness-brainstorming` or `harness-planning`.
13
+
14
+ ## Process
15
+
16
+ ### Iron Law
17
+
18
+ **Every gap is either resolved in the interview or shipped as an explicit client-facing question — never silently dropped.** A BRD that hides what it does not know is worse than no BRD: it launders assumptions into requirements. If you cannot answer a gap and did not surface it in `gaps.md`, STOP and add it.
19
+
20
+ ---
21
+
22
+ ### Phase 1: INGEST — Gather the Raw Material
23
+
24
+ 1. **Resolve the engagement slug.** From the `engagement` argument, or ask the SA for a short name. This sets `docs/inception/<engagement>/` and the roadmap milestone `Inception: <engagement>`.
25
+ 2. **Ingest the diagram.** If a `diagram` argument (or a discoverable diagram) is present, parse it by calling `ingest_source({ path, source: "diagrams" })` (harness MCP) — the shipped diagram path handles diagram-as-code (Mermaid/D2/PlantUML) and image attachments (vision analysis). Then read the extracted entities and flows back via `gather_context` / `query_graph`. **Do not build a new parser** — reuse `ingest_source`.
26
+ 3. **Soft-degrade when parsing is unavailable.** If diagram parsing is unavailable or the diagram is unreadable, continue with **notes-only intake** and record a gap: `"diagram not machine-read; confirm entities and flows manually."` Do not fail.
27
+ 4. **Ingest the notes.** Load the client conversation notes / transcript from the `notes` argument or as provided. Call `gather_context` to pull any existing project/business knowledge that grounds the domain.
28
+ 5. **Normalize into intake.** Produce a structured intake: `{ entities[], flows[], notes }`. State the entities and flows back to the SA in one short summary and confirm before drafting.
29
+
30
+ ---
31
+
32
+ ### Phase 2: DRAFT-BRD — Synthesize the First Draft
33
+
34
+ 1. **Write the BRD** to `docs/inception/<engagement>/brd.md` with these sections, each present even if thin: _Context, Business Objectives, Scope, Functional Requirements, Non-Functional Requirements, Assumptions, Constraints, Out-of-Scope, Open Questions._
35
+ 2. **Phrase behavioral requirements with EARS patterns:**
36
+ - Event-driven: "When [trigger], the system shall [response]."
37
+ - Unwanted: "If [condition], then the system shall not [behavior]."
38
+ 3. **Tag gaps against the fixed BRD completeness rubric** (see below). Every rubric miss becomes a gap with `{ id, brdSection, question, severity: blocker|important|nice, status: open }`. Do not invent facts to fill a section — an empty-because-unknown section is a gap, not a place to guess.
39
+ 4. **Cite the source** of each requirement (`diagram`, `notes`, or later `interview`) so the SA can trace it.
40
+
41
+ #### BRD completeness rubric
42
+
43
+ - Each BRD section is non-empty and internally consistent.
44
+ - Every diagram entity and flow maps to ≥1 functional requirement (or to an explicit gap).
45
+ - Every functional requirement has an **actor + trigger + response**.
46
+ - Every non-functional requirement is measurable (a number or a testable condition), else it is a gap.
47
+ - Scope and Out-of-Scope do not contradict each other.
48
+
49
+ ---
50
+
51
+ ### Phase 3: GAP-INTERVIEW — Resolve What You Can
52
+
53
+ 1. **Ask ONE question at a time, in plain text.** Order the gap queue by severity (`blocker` → `important` → `nice`). Ask the highest-severity open gap first, wait for the answer, then continue.
54
+
55
+ **Ask directly in your reply. Do NOT route questions through `emit_interaction`, `AskUserQuestion`, or any tool** — those do not reliably surface the question to the human. Plain text in your own message is the only channel that reaches the SA across every client (Claude Code, Cursor, Codex, Gemini CLI).
56
+
57
+ Present each gap as a scannable multiple-choice table where options exist, and state a recommendation:
58
+
59
+ ```markdown
60
+ ### Gap G3 (blocker): What authenticates end users?
61
+
62
+ | | A) Client SSO (SAML/OIDC) | B) Local accounts | C) Unknown — ask client |
63
+ | ----------- | ------------------------- | ----------------- | ----------------------- |
64
+ | **Implies** | IdP integration work | Password storage | Blocks scoping |
65
+ | **Risk** | Depends on client IdP | Security burden | — |
66
+
67
+ **Recommendation:** likely A given the enterprise diagram — confirm the IdP.
68
+ ```
69
+
70
+ 2. **Fold each answer back into the BRD.** Update the relevant section, add the requirement (source: `interview`), and move the gap `open → resolved` with the captured answer.
71
+ 3. **Mark unresolvable gaps client-facing.** If the SA cannot answer (only the client can), keep the gap `open` and phrase it as a question to ask the client.
72
+ 4. **Stop when the queue is drained** — every gap is either `resolved` or `open` (client-facing). Do not loop past a drained queue inventing new questions.
73
+
74
+ ---
75
+
76
+ ### Phase 4: FINALIZE — Ship and Hand Off
77
+
78
+ 1. **Write `gaps.md`** to `docs/inception/<engagement>/gaps.md` with two sections: **Resolved** (gap + captured answer) and **Open / chase-with-client** (each phrased as a question to ask the client).
79
+ 2. **Offer a STRATEGY.md seed.** In plain text, offer to seed the engagement's strategy via `/harness:strategy`, using the BRD's Business Objectives + Scope as grounding. **Never write `STRATEGY.md` yourself** — dispatch `harness-strategy` if the SA accepts.
80
+ 3. **Fan out into roadmap candidates.** Decompose the BRD scope into N candidate work items — each `{ title, summary, brdRefs[], rationale }`. Present them to the SA for a quick confirm/prune, then write each accepted item via `manage_roadmap` action `add`, `status: backlog`, `milestone: "Inception: <engagement>"`, with the BRD section reference in the summary. One BRD produces many rows — do not collapse the engagement into a single item.
81
+ 4. **Emit the handoff.** Record the transition to the roadmap/brainstorming flow via `emit_interaction`. State plainly that each roadmap item now enters the existing `roadmap-pilot → brainstorming → spec → plan → execute` pipeline. **Do not author a spec** — hand off to `harness-brainstorming` per item when the SA is ready.
82
+
83
+ ---
84
+
85
+ ## Harness Integration
86
+
87
+ - **`gather_context`** — Phase 1: pull existing project/business knowledge to ground the domain.
88
+ - **`ingest_source` (`source: "diagrams"`)** — Phase 1: parse diagrams (diagram-as-code + image vision) into the knowledge graph; read the extracted entities/flows back via `gather_context` / `query_graph`. Never reimplement the parser.
89
+ - **`read_strategy`** — Phase 4: read `STRATEGY.md` (if present) to align the BRD; never write it.
90
+ - **`manage_roadmap` (action `add`)** — Phase 4: create backlog roadmap rows from the BRD fan-out.
91
+ - **`emit_interaction`** — Phase 4: record the handoff transition to the roadmap/brainstorming flow.
92
+ - **`harness validate`** — After finalize: verify artifact placement and project health.
93
+
94
+ ## Success Criteria
95
+
96
+ - Running the skill with a diagram + notes produces `docs/inception/<engagement>/brd.md` with all required sections, none empty.
97
+ - Every diagram entity/flow maps to ≥1 BRD requirement or to an explicit gap.
98
+ - `gaps.md` exists and separates **Resolved** from **Open/client-facing**; every open gap is phrased as a question.
99
+ - The gap interview asked one question at a time and folded each answer into the BRD (resolved gaps moved `open → resolved`).
100
+ - `finalize` created ≥1 candidate roadmap row via `manage_roadmap`, each linking back to a BRD section.
101
+ - `finalize` offered a `STRATEGY.md` seed via `/harness:strategy` and did not write `STRATEGY.md` directly.
102
+ - Behavioral functional requirements use EARS phrasing.
103
+ - When diagram parsing was unavailable, the skill degraded to notes-only and recorded a gap rather than failing.
104
+ - No spec/proposal was authored by this skill.
105
+
106
+ ## Examples
107
+
108
+ ### Example: retail loyalty engagement from a diagram + call notes
109
+
110
+ **INGEST:**
111
+
112
+ ```
113
+ engagement: acme-loyalty
114
+ diagram: architecture.mmd (Mermaid) → parsed: entities [POS, Loyalty API, CRM, Rewards Engine], flows [POS→Loyalty API→CRM]
115
+ notes: kickoff-call.md → loaded. gather_context: existing "loyalty" business facts surfaced.
116
+ Confirmed entities/flows with SA. Proceed.
117
+ ```
118
+
119
+ **DRAFT-BRD:** Wrote `docs/inception/acme-loyalty/brd.md`. 9 sections. Tagged 6 gaps:
120
+ G1 (blocker) no auth model; G2 (blocker) Rewards Engine has no defined trigger; G3 (important) no NFR for POS latency; G4 (important) CRM data residency unknown; G5 (nice) reporting cadence; G6 (blocker) "Rewards Engine" entity maps to no requirement.
121
+
122
+ **GAP-INTERVIEW:**
123
+
124
+ ```
125
+ G1: "What authenticates end users? A) Client SSO B) Local C) Unknown" → SA: "A, Okta OIDC." → folded in.
126
+ G2: "When does the Rewards Engine fire? A) On transaction B) Batch nightly C) Unknown" → SA: "A." → EARS: "When a qualifying transaction is recorded, the system shall evaluate reward eligibility."
127
+ G3: "POS latency budget?" → SA: "client must confirm." → kept open, client-facing.
128
+ G4: "CRM data residency?" → SA: "client must confirm." → kept open, client-facing.
129
+ G6: resolved by G2. G5: SA: "monthly." → folded in.
130
+ ```
131
+
132
+ **FINALIZE:**
133
+
134
+ ```
135
+ Wrote gaps.md → Resolved: G1,G2,G5,G6 | Open/client-facing: G3 (latency), G4 (residency).
136
+ Offered STRATEGY.md seed → SA accepted → dispatched /harness:strategy.
137
+ Roadmap fan-out (milestone "Inception: acme-loyalty", backlog):
138
+ - "POS ↔ Loyalty API integration" (brd: Scope, FR-1)
139
+ - "Rewards Engine eligibility rules" (brd: FR-4)
140
+ - "Okta OIDC authentication" (brd: FR-2)
141
+ - "CRM sync + residency compliance" (brd: FR-5, NFR-2)
142
+ Emitted handoff → each item enters roadmap-pilot → brainstorming. No spec authored.
143
+ ```
144
+
145
+ ## Gates
146
+
147
+ - **No dropped gaps.** Every gap is `resolved` or shipped as an `open` client-facing question in `gaps.md`. A gap that is neither = Iron Law violation; stop and fix.
148
+ - **No guessed requirements.** A BRD section that is unknown is a gap, not a place to invent facts. Fabricating a requirement to fill a section is a hard stop.
149
+ - **No writing `STRATEGY.md`.** This skill reads strategy and offers to seed it via `/harness:strategy`. Writing `STRATEGY.md` directly = gate violation.
150
+ - **No authoring specs.** This skill stops at BRD + roadmap seeding. Writing a `proposal.md` = gate violation; hand off to `harness-brainstorming`.
151
+ - **No single-item collapse.** If the BRD scope contains multiple independent capabilities, `finalize` must produce multiple roadmap rows. Collapsing an engagement into one row defeats the fan-out.
152
+ - **No hard failure on missing diagram.** Absent/unreadable diagram → notes-only + recorded gap. Aborting the run because a diagram would not parse = gate violation.
153
+
154
+ ## Escalation
155
+
156
+ - **Diagram parses but entities contradict the notes:** Do not silently pick one. Surface the contradiction as a `blocker` gap and ask the SA which source is authoritative.
157
+ - **The SA cannot answer any blocker gap:** The engagement is too early for a BRD. Report: "N blocker gaps are all client-facing; this needs a client conversation before a BRD is meaningful. Ship the gap-list as a client questionnaire and pause."
158
+ - **Scope keeps expanding during the interview:** Stop. Report: "Scope has grown beyond the ingested material. Should we (A) bound the BRD to the original diagram/notes and log the rest as follow-up, or (B) re-ingest expanded material first?"
159
+ - **`manage_roadmap` is unavailable:** Write the candidate items into `gaps.md` under a "Proposed roadmap items" heading and report: "Roadmap seeding skipped (manage_roadmap unavailable). Re-run finalize when MCP is restored."
160
+ - **More than ~15 gaps after drafting:** The intake is too raw. Report and propose narrowing the engagement scope before interviewing, rather than running a 15-question interview.
161
+
162
+ ## Rationalizations to Reject
163
+
164
+ | Rationalization | Reality |
165
+ | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
166
+ | "The diagram implies the auth model, so I'll just write it as a requirement" | An implication is not a confirmation. Diagram-implied facts that the client has not stated are gaps — surface them, don't launder them into requirements. |
167
+ | "This gap is minor, I'll leave it out of gaps.md to keep it clean" | The Iron Law is explicit: every gap is resolved or shipped. A gap you drop is an assumption the client discovers in production. `nice`-severity still ships. |
168
+ | "I have enough to draft a proposal, I'll just write the spec too" | Product Advisor stops at BRD + roadmap seeding. Authoring a spec skips `harness-brainstorming`'s design exploration, which is exactly where the gaps get weighed against approaches. |
169
+ | "The BRD's objectives are clear, I'll seed STRATEGY.md directly to save a step" | This skill never writes `STRATEGY.md`. The `harness-strategy` boundary exists so strategy stays a deliberate, pushback-gated human commitment — not a side effect of inception. |
170
+ | "The engagement is really one big project, I'll make one roadmap row" | A BRD describes a solution scope that fans out into many work items. One row defeats the whole handoff — each capability needs its own brainstorming → spec cycle. |
171
+ | "The diagram won't parse, so I can't run — I'll abort" | Notes-only intake is a first-class path. Degrade, record the diagram as a gap, and continue. Aborting throws away the requirements the notes already contain. |
172
+
173
+ ## Red Flags
174
+
175
+ | Flag | Corrective Action |
176
+ | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
177
+ | "I'll fill the empty NFR section with reasonable defaults" | STOP. Unknown NFRs are gaps. Defaults you invent become requirements no one agreed to. Tag it as a gap and ask. |
178
+ | "The interview is dragging; I'll batch the remaining questions into one message" | STOP. One question at a time is prescribed — batched questions get partial answers and lose the fold-back loop. Ask the next single highest-severity gap. |
179
+ | "The SA said 'just make sensible assumptions'" | STOP. Assumptions belong in the BRD's **Assumptions** section, labeled as assumptions, and the underlying unknowns stay in `gaps.md` as client-facing. Do not convert assumptions into silent requirements. |
180
+ | `// TODO: confirm with client` left inside brd.md functional requirements | STOP. Confirmation-needed items are gaps, not requirements. Move them to `gaps.md` (Open/client-facing) and keep the BRD's requirements limited to what is actually known. |
181
+
182
+ ---
183
+
184
+ <!--
185
+ ## Skill Test Scenarios
186
+
187
+ ### Scenario 1: Gate — "No dropped gaps"
188
+ Input: Drafting produces a `nice`-severity gap (reporting cadence) the SA never answers and cannot be bothered to log.
189
+ Expected: Agent keeps the gap and writes it to gaps.md under Open/client-facing rather than dropping it; cites the Iron Law / "No dropped gaps" gate.
190
+
191
+ ### Scenario 2: Rationalization — "I have enough to draft a proposal, I'll just write the spec too"
192
+ Input: After a clean interview the agent is tempted to write docs/changes/<x>/proposal.md.
193
+ Expected: Agent refuses, finalizes BRD + roadmap fan-out, and hands off to harness-brainstorming per item — no spec authored (gate: "No authoring specs").
194
+
195
+ ### Scenario 3: Gate/Escalation — soft-degrade on unreadable diagram
196
+ Input: The provided diagram is a binary image the environment cannot vision-parse.
197
+ Expected: Agent does not abort; runs notes-only intake and records "diagram not machine-read; confirm entities manually" as a gap (gate: "No hard failure on missing diagram").
198
+
199
+ ### Scenario 4: Rationalization — "This is really one big project, I'll make one roadmap row"
200
+ Input: A BRD with 4 independent capabilities; agent tempted to add a single "Acme engagement" roadmap row.
201
+ Expected: Agent fans out into one row per capability with BRD backrefs (gate: "No single-item collapse").
202
+ -->
@@ -0,0 +1,74 @@
1
+ name: product-advisor
2
+ version: "0.1.0"
3
+ description: Upstream client-inception skill. Ingests a diagram + client conversation notes, drafts a Business Requirements Document (BRD), detects gaps against a fixed completeness rubric, resolves them through a one-question-at-a-time interview with the solution architect, then fans the BRD out into candidate roadmap items and offers a STRATEGY.md seed. Reads but never writes STRATEGY.md; never authors specs (harness-brainstorming owns that). The pre-inception front door to the harness pipeline.
4
+ stability: static
5
+ cognitive_mode: configuration-interviewer
6
+ triggers:
7
+ - manual
8
+ platforms:
9
+ - claude-code
10
+ - gemini-cli
11
+ - cursor
12
+ - codex
13
+ tools:
14
+ - Bash
15
+ - Read
16
+ - Write
17
+ - Edit
18
+ - Glob
19
+ - Grep
20
+ cli:
21
+ command: harness skill run product-advisor
22
+ args:
23
+ - name: engagement
24
+ description: Short name/slug for the client engagement. Used for the docs/inception/<engagement>/ artifact directory and the roadmap milestone.
25
+ required: false
26
+ - name: diagram
27
+ description: Path to a diagram (Mermaid/D2/PlantUML source or an image attachment) to ingest. Optional — the skill soft-degrades to notes-only when absent or unreadable.
28
+ required: false
29
+ - name: notes
30
+ description: Path to client conversation notes / call transcript to ingest.
31
+ required: false
32
+ mcp:
33
+ tool: run_skill
34
+ input:
35
+ skill: product-advisor
36
+ path: string
37
+ type: rigid
38
+ tier: 1
39
+ phases:
40
+ - name: ingest
41
+ description: Load diagram(s) + client conversation notes; reuse the business-knowledge diagram/vision path; normalize into a structured intake (entities, flows, notes). Soft-degrade to notes-only when diagram parsing is unavailable and record it as a gap.
42
+ required: true
43
+ - name: draft-brd
44
+ description: Synthesize a first BRD from intake into docs/inception/<engagement>/brd.md; tag every under-specified area as a gap against the fixed BRD completeness rubric. Behavioral requirements use EARS phrasing.
45
+ required: true
46
+ - name: gap-interview
47
+ description: Walk the solution architect through the gap queue one question at a time (plain-text tables); fold each answer back into the BRD; mark unresolved gaps as client-facing questions.
48
+ required: true
49
+ - name: finalize
50
+ description: Write brd.md + gaps.md (Resolved vs Open/client-facing); offer a STRATEGY.md seed via /harness:strategy; fan the BRD out into N candidate roadmap rows via manage_roadmap (status backlog) with backrefs to BRD sections; emit the handoff to the roadmap/brainstorming flow.
51
+ required: true
52
+ state:
53
+ persistent: true
54
+ files:
55
+ - docs/inception/
56
+ depends_on:
57
+ - harness-strategy
58
+ - harness-brainstorming
59
+ related_skills:
60
+ - harness-strategy
61
+ - harness-brainstorming
62
+ - harness-ideate
63
+ - harness-roadmap-pilot
64
+ keywords:
65
+ - product-advisor
66
+ - BRD
67
+ - business-requirements
68
+ - requirements-elicitation
69
+ - gap-analysis
70
+ - diagram-ingestion
71
+ - roadmap-decomposition
72
+ - pre-inception
73
+ - solution-architect
74
+ - upstream-grounding
@@ -204,7 +204,7 @@ Persist findings to `{sessionDir}/phase-{N}-review.json`. No blocking → PHASE_
204
204
  ### DONE
205
205
 
206
206
  1. Present: total phases, tasks, retries, time, `finalReview.status` + findings count, any overridden findings.
207
- 2. Ask "Create a PR? (yes / no)."
207
+ 2. Ask "Create a PR? (yes / no)." When creating the PR, include a bare closing line `Closes #<N>` where `<N>` is the issue number from the roadmap row's `External-ID`. The keyword MUST sit IMMEDIATELY before the ref — no intervening words (`Closes #<N>`, never `Closes roadmap #<N>`), or GitHub will not link/close the issue and roadmap auto-done will skip the row.
208
208
  3. Write final handoff to `{sessionDir}/handoff.json`. Append learnings to `.harness/learnings.md`. Call `promoteSessionLearnings(projectPath, sessionSlug)`. If learnings count > 30, suggest `harness learnings prune`.
209
209
  4. If `docs/roadmap.md` exists: call `manage_roadmap update` to set feature done. Skip if not found.
210
210
  5. Write final `writeSessionSummary()`. Set `currentState: "DONE"` in autopilot-state.json.
@@ -254,13 +254,14 @@ Persist findings to `{sessionDir}/phase-{N}-review.json`. No blocking → PHASE_
254
254
 
255
255
  ## Rationalizations to Reject
256
256
 
257
- | Rationalization | Reality |
258
- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
259
- | "Low complexity means I can skip APPROVE_PLAN" | Low complexity means auto-approval only when no signals fire. Signals override complexity. |
260
- | "I can inline planning logic instead of dispatching to harness-planner" | Iron Law. Autopilot delegates, never reimplements. No exceptions. |
261
- | "Retry budget exhausted but one more approach might work" | 3-attempt budget prevents compounding failure. Exceeding it without human input is unrecoverable. |
262
- | "Keeping research in conversation is faster than scratchpad" | Scratchpad gated by rigor level. At standard/thorough, >500 words must go to scratchpad. |
263
- | "Plan auto-approved, so I can skip recording the decision" | Every approval—auto or manual—is recorded in `decisions[]`. That array is the audit trail. |
257
+ | Rationalization | Reality |
258
+ | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
259
+ | "Low complexity means I can skip APPROVE_PLAN" | Low complexity means auto-approval only when no signals fire. Signals override complexity. |
260
+ | "I can inline planning logic instead of dispatching to harness-planner" | Iron Law. Autopilot delegates, never reimplements. No exceptions. |
261
+ | "Retry budget exhausted but one more approach might work" | 3-attempt budget prevents compounding failure. Exceeding it without human input is unrecoverable. |
262
+ | "Keeping research in conversation is faster than scratchpad" | Scratchpad gated by rigor level. At standard/thorough, >500 words must go to scratchpad. |
263
+ | "Plan auto-approved, so I can skip recording the decision" | Every approval—auto or manual—is recorded in `decisions[]`. That array is the audit trail. |
264
+ | "`Closes roadmap #123` reads fine, GitHub will figure out the issue" | An intervening word breaks GitHub's closing-keyword parser: `closingIssuesReferences` stays empty and auto-done leaves the row `planned`. Use a bare `Closes #123`. |
264
265
 
265
266
  ## Success Criteria
266
267
 
@@ -0,0 +1,86 @@
1
+ # Pre-Merge Brief
2
+
3
+ > The harness pointed at the human who clicks merge. A thin wrapper over `harness pre-merge-brief` that composes a senior-facing accountability brief — the diff summary, the multi-persona review verdict (from `review-ci --json`), the curated **Signal status** snapshot, the outcome-eval result, and a derived **"👀 Worth your eyes"** section — and posts it as a single sticky PR comment (upsert by marker). All composition and degradation logic lives in the command; this skill orchestrates invocation, reports which sections degraded, and hands off. Advisory and non-blocking: the brief never flips the review gate.
4
+
5
+ ## When to Use
6
+
7
+ - On every PR, so the senior engineer who merges sees "you are pushing this — here's what deserves your eyes" before they click merge.
8
+ - `on_pr` (dogfooded via the `required-review` workflow, reusing that run's `review-ci --json` artifact) and `manual` (a senior running it locally against the current branch's PR).
9
+ - NOT as a merge gate — the acknowledgment gate is deliberately deferred (spec D3). The brief is advisory; the review gate's exit code is what blocks.
10
+ - NOT a replacement for `review-ci` — this skill CONSUMES the review verdict, it does not re-run the review (spec D1).
11
+ - NOT for recomputing signals a different way — signals come from `@harness-engineering/signals` via the command (spec D2/D6).
12
+
13
+ ## Process
14
+
15
+ ### Phase 1: GATHER — Resolve inputs
16
+
17
+ 1. Locate the `review-ci --json` artifact for this run and record its path for `--from`. In CI it is the JSON the `required-review` workflow's `review-ci` step wrote (e.g. `/tmp/review.json`); locally, run `harness review-ci --json <path>` first if a verdict is wanted. Absent `--from` is tolerated — the review section degrades to "unavailable".
18
+ 2. Resolve the diff range for `--diff` (default `origin/<base>...HEAD` via the command's own resolver). Override only when the base is non-standard.
19
+ 3. Resolve the head sha for `--head` (default `git rev-parse HEAD`) — used for the `execution_outcome` graph lookup. Pre-merge the node is commonly absent, which is the documented degradation path, not an error.
20
+ 4. If posting (`--comment`), confirm `gh` is authenticated. Delivery failure never crashes the command (spec S1): it prints the brief and warns, still exiting 0.
21
+
22
+ ### Phase 2: COMPOSE — Run the command
23
+
24
+ Invoke `harness pre-merge-brief` with the resolved inputs:
25
+
26
+ ```bash
27
+ harness pre-merge-brief --from <review.json> --diff <range> --head <sha> [--comment]
28
+ ```
29
+
30
+ The command builds the six-section brief (marker + header → Diff summary → Review verdict → **Signal status** → Outcome evaluation → **👀 Worth your eyes**) and, with `--comment`, upserts the sticky PR comment by its marker (`<!-- harness:pre-merge-brief -->`) — patching the existing comment in place rather than posting a new one on each push. Without `--comment` it prints the brief to stdout. Each input degrades independently to an explicit "unavailable" line; the command exits 0 on a successful render regardless of which inputs were present.
31
+
32
+ ### Phase 3: REPORT — Surface what matters
33
+
34
+ 1. Report which sections rendered with real data and which degraded to "unavailable / not yet evaluated", so the senior knows the brief's coverage.
35
+ 2. Surface the **"👀 Worth your eyes"** items verbatim — the union of blocking review findings, signals in `warn`/`alert`, and unmet outcome criteria. This is the section the accountable human should read first.
36
+
37
+ ### Phase 4: HANDOFF — Advisory transition
38
+
39
+ Emit the transition via `emit_interaction`. The brief is advisory and non-blocking: it never flips the review gate's pass/fail status (spec D3, D4). In the dogfood workflow the brief step is `continue-on-error`, so a brief failure never fails the PR.
40
+
41
+ ## Harness Integration
42
+
43
+ - **`harness pre-merge-brief`** — the command this skill wraps. Flags: `--from <path>` (review-ci verdict JSON), `--comment` (sticky-upsert to the current branch's PR via `gh`), `--diff <range>`, `--head <sha>`. Pure render (`buildBriefBody`) + injected seams (`postBrief`, `RunGit`, graph store); no `process.exit` in the pure core.
44
+ - **`review-ci`** — upstream producer of the review verdict. This skill reuses its `--json` artifact via `--from`; it never re-runs the review (D1). `review-ci` remains the single source of review truth.
45
+ - **`@harness-engineering/signals`** — the shared leaf package (extracted in spec Phase 1/D6) providing `gatherSignals`. The command computes the Signal status snapshot from it; the CLI does not route signal computation through the dashboard app.
46
+ - **`execution_outcome` graph nodes** — the outcome-eval result, looked up by head sha from `.harness/graph`; commonly absent pre-merge (degrades to "not yet evaluated").
47
+ - **`required-review.yml` (dogfood)** — the `on_pr` delivery path: a `continue-on-error` step runs the brief after the existing `review-ci` run, reusing its artifact (spec Phase 4/D4). Adopter template graduation is a tracked follow-up (D5).
48
+
49
+ ## Gates
50
+
51
+ - **Never re-run the review.** Consume `review-ci --json`; do not invoke the review pipeline from this skill (D1).
52
+ - **Never block the merge.** The brief is advisory; the review gate's exit code is authoritative. No acknowledgment gate in v1 (D3).
53
+ - **Never crash `--comment`.** A `gh`/PR delivery failure prints the brief and warns, still exiting 0 (S1).
54
+ - **Thin wrapper only.** No brief composition, signal computation, or union logic in the skill — all of it lives in the command.
55
+
56
+ ## Success Criteria
57
+
58
+ Maps to spec `docs/changes/senior-accountability-surface/proposal.md`. This skill satisfies criterion #2 (the skill wrapping the command, `on_pr` + `manual`) and supports #1/#3/#4 by driving the command whose pure functions are unit-tested. Introduces no new `harness validate` findings.
59
+
60
+ ## Escalation
61
+
62
+ - **No PR for the current branch (`--comment`).** The command warns and prints the brief to stdout instead of posting, still exiting 0. Surface the warning; do not treat it as a failure.
63
+ - **No review artifact (`--from` missing/absent).** The review-verdict section degrades to "unavailable". If a verdict is wanted, run `harness review-ci --json <path>` first and pass it.
64
+ - **`gh` unauthenticated or API error while posting.** Delivery fails soft (brief printed, one-line stderr warning, exit 0). Fix `gh auth` and re-run; nothing is lost.
65
+ - **Signals or outcome-eval unavailable.** Each degrades independently to its "unavailable"/"not yet evaluated" line — expected pre-merge, not an error. Do not block the brief on them.
66
+ - **Someone asks to make the brief block merges.** That is the deferred acknowledgment gate (spec D3), a separate future spec. Keep the brief advisory; point them at the follow-up roadmap row.
67
+
68
+ ## Examples
69
+
70
+ ### Example: brief on a PR in CI (dogfood)
71
+
72
+ The `required-review.yml` workflow runs `review-ci --json /tmp/review.json`, then this skill's command:
73
+
74
+ ```bash
75
+ harness pre-merge-brief --from /tmp/review.json --diff "origin/main...HEAD" --comment
76
+ ```
77
+
78
+ The brief is composed and upserted as a sticky PR comment. The review found one blocking finding and two `alert` signals, so **👀 Worth your eyes** lists exactly those three; the outcome section shows "not yet evaluated" (no `execution_outcome` node pre-merge). The step is `continue-on-error`, so even if `gh` posting fails the review gate is unaffected.
79
+
80
+ ### Example: senior running it locally
81
+
82
+ ```bash
83
+ harness pre-merge-brief --comment
84
+ ```
85
+
86
+ No `--from`, so the review-verdict section renders "unavailable"; signals are gathered live and the diff summary uses the default `origin/<base>...HEAD` range. The senior sees the current signal status and diff before clicking merge.
@@ -0,0 +1,67 @@
1
+ name: harness-pre-merge-brief
2
+ version: "0.1.0"
3
+ description: >-
4
+ Thin-wrapper skill that runs the `harness pre-merge-brief` command to compose
5
+ and post the senior-facing pre-merge accountability brief — the diff summary,
6
+ the multi-persona review verdict (from review-ci --json), the curated Signal
7
+ status snapshot, the outcome-eval result, and a derived "Worth your eyes"
8
+ section — as a single sticky PR comment (upsert by marker). All composition and
9
+ degradation logic lives in the command; the skill orchestrates invocation,
10
+ communicates which sections degraded to "unavailable", and hands off. Runs on
11
+ on_pr and manual. The harness pointed at the human who clicks merge.
12
+ stability: draft
13
+ cognitive_mode: constructive-architect
14
+ triggers:
15
+ - on_pr
16
+ - manual
17
+ platforms:
18
+ - claude-code
19
+ - gemini-cli
20
+ - cursor
21
+ - codex
22
+ tools:
23
+ - Bash
24
+ - Read
25
+ - Glob
26
+ - Grep
27
+ - emit_interaction
28
+ cli:
29
+ command: harness pre-merge-brief
30
+ args:
31
+ - name: from
32
+ description: Path to the review-ci --json CiReviewResult artifact to reuse
33
+ required: false
34
+ - name: comment
35
+ description: Upsert the brief as a sticky PR comment via gh (by marker)
36
+ required: false
37
+ - name: diff
38
+ description: "git diff range for the diff summary (e.g. origin/main...HEAD)"
39
+ required: false
40
+ - name: head
41
+ description: "head commit sha for the outcome-eval lookup (default: git rev-parse HEAD)"
42
+ required: false
43
+ mcp:
44
+ tool: run_skill
45
+ input:
46
+ skill: harness-pre-merge-brief
47
+ path: string
48
+ type: rigid
49
+ tier: 2
50
+ phases:
51
+ - name: gather
52
+ description: Locate the review-ci --json artifact, resolve the diff range, confirm gh auth for --comment
53
+ required: true
54
+ - name: compose
55
+ description: Run `harness pre-merge-brief` with the resolved inputs; the command builds the brief and (with --comment) upserts the sticky PR comment
56
+ required: true
57
+ - name: report
58
+ description: Report which sections rendered and which degraded to "unavailable"; surface the "Worth your eyes" items
59
+ required: true
60
+ - name: handoff
61
+ description: Emit the transition; the brief is advisory (non-blocking) and never flips the review gate
62
+ required: true
63
+ state:
64
+ persistent: false
65
+ depends_on:
66
+ - harness-code-review
67
+ - outcome-eval