@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.
- package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +9 -8
- package/dist/agents/skills/claude-code/pre-merge-brief/SKILL.md +86 -0
- package/dist/agents/skills/claude-code/pre-merge-brief/skill.yaml +67 -0
- package/dist/agents/skills/claude-code/product-advisor/SKILL.md +202 -0
- package/dist/agents/skills/claude-code/product-advisor/skill.yaml +74 -0
- package/dist/agents/skills/codex/harness-autopilot/SKILL.md +9 -8
- package/dist/agents/skills/codex/pre-merge-brief/SKILL.md +86 -0
- package/dist/agents/skills/codex/pre-merge-brief/skill.yaml +67 -0
- package/dist/agents/skills/codex/product-advisor/SKILL.md +202 -0
- package/dist/agents/skills/codex/product-advisor/skill.yaml +74 -0
- package/dist/agents/skills/cursor/harness-autopilot/SKILL.md +9 -8
- package/dist/agents/skills/cursor/pre-merge-brief/SKILL.md +86 -0
- package/dist/agents/skills/cursor/pre-merge-brief/skill.yaml +67 -0
- package/dist/agents/skills/cursor/product-advisor/SKILL.md +202 -0
- package/dist/agents/skills/cursor/product-advisor/skill.yaml +74 -0
- package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +9 -8
- package/dist/agents/skills/gemini-cli/pre-merge-brief/SKILL.md +86 -0
- package/dist/agents/skills/gemini-cli/pre-merge-brief/skill.yaml +67 -0
- package/dist/agents/skills/gemini-cli/product-advisor/SKILL.md +202 -0
- package/dist/agents/skills/gemini-cli/product-advisor/skill.yaml +74 -0
- package/dist/{agents-md-7OSNWU52.js → agents-md-7L4PKKOM.js} +4 -4
- package/dist/analyzer-XRCV63KC-HLTEIKAJ.js +26 -0
- package/dist/{architecture-2XYGJGT3.js → architecture-RCHFDI7E.js} +5 -5
- package/dist/{assess-project-3KPP2D6M.js → assess-project-YUDPNRS6.js} +5 -3
- package/dist/bin/harness-mcp.js +16 -16
- package/dist/bin/harness.js +27 -27
- package/dist/{check-phase-gate-46U5AAXE.js → check-phase-gate-56GS3A72.js} +5 -5
- package/dist/{chunk-MSBJ445U.js → chunk-4SKWGVYD.js} +5 -5
- package/dist/{chunk-CLI4K2CH.js → chunk-4U5LDFCY.js} +1 -1
- package/dist/{chunk-6YXCZV33.js → chunk-ABRYIEWJ.js} +1090 -714
- package/dist/{chunk-AK67S3O4.js → chunk-AU4YPEIE.js} +3 -3
- package/dist/{chunk-BV45354Q.js → chunk-DGVT4DBI.js} +9 -9
- package/dist/{chunk-363V6GPR.js → chunk-GLHLXTKC.js} +9 -9
- package/dist/{chunk-VTUINXWR.js → chunk-GSYBGOY3.js} +1 -1
- package/dist/{chunk-FZ4Q73HA.js → chunk-IGWJRAJT.js} +1 -1
- package/dist/{chunk-S2RQPPL6.js → chunk-N4AI2WFH.js} +1 -1
- package/dist/{chunk-HXMAIVV2.js → chunk-NCMJXBEO.js} +1 -1
- package/dist/{chunk-ZEYAOYJL.js → chunk-OZSKLJQW.js} +1 -1
- package/dist/{chunk-VTU3QOJT.js → chunk-P4NA5OQX.js} +1 -1
- package/dist/{chunk-WL3O2PKJ.js → chunk-RY2U77OY.js} +8 -8
- package/dist/{chunk-TTWNGOBT.js → chunk-RZQZXWEL.js} +32 -7
- package/dist/{chunk-KLPX55TI.js → chunk-UACYZCW4.js} +239 -146
- package/dist/{chunk-IYWT3JJW.js → chunk-VG4G3R2V.js} +1 -1
- package/dist/{chunk-PP6ZRL5T.js → chunk-WZJR6SOI.js} +536 -422
- package/dist/{chunk-PHX45JYN.js → chunk-XW5XVVMI.js} +2 -2
- package/dist/{chunk-MYVTYFQD.js → chunk-XZNCONFG.js} +1 -1
- package/dist/{chunk-GXCPDAS5.js → chunk-Y33P35U3.js} +26 -8
- package/dist/{chunk-XFHZ7GCI.js → chunk-Y5HPJMTM.js} +19 -3
- package/dist/{chunk-N55WOGN3.js → chunk-YJYUJSWK.js} +59 -21
- package/dist/{chunk-SPE7P4GL.js → chunk-YWRPQZL7.js} +1 -1
- package/dist/{chunk-6NCREWWM.js → chunk-YXOPQEFZ.js} +3 -3
- package/dist/{chunk-2N4OENGE.js → chunk-YYFSFSB3.js} +1 -1
- package/dist/{chunk-ERILXQBP.js → chunk-Z4XWWNYX.js} +615 -433
- package/dist/{chunk-HMW3C5DP.js → chunk-ZU6T7W3U.js} +2 -2
- package/dist/{ci-workflow-XJN4UO3Q.js → ci-workflow-TFAA5BK7.js} +4 -4
- package/dist/{dist-OWHMNL4W.js → dist-DWBTZXR5.js} +1 -1
- package/dist/{dist-IPVFYGY2.js → dist-MCTEX5QH.js} +5 -3
- package/dist/{docs-RSFZTNPG.js → docs-BBMAN3CY.js} +5 -5
- package/dist/{engine-DJIHY4JT.js → engine-R2YH74AL.js} +4 -4
- package/dist/{entropy-EAEKJKRM.js → entropy-5UP5N6AF.js} +7 -4
- package/dist/{feedback-JT5X3DBC.js → feedback-6MDCCFZL.js} +1 -1
- package/dist/{generate-agent-definitions-CC6KED3E.js → generate-agent-definitions-KKAN5DB5.js} +5 -5
- package/dist/{glob-helper-GLZAURJC.js → glob-helper-VR6UCZZB.js} +1 -1
- package/dist/{graph-loader-HHXN5FLP.js → graph-loader-STFGYKZH.js} +1 -1
- package/dist/hooks/sentinel-pre.js +15 -138
- package/dist/index.d.ts +61 -0
- package/dist/index.js +27 -27
- package/dist/{loader-UWNVTYBY.js → loader-2WT2ZE2T.js} +4 -4
- package/dist/{mcp-TCLNK7HG.js → mcp-5V4LPMB3.js} +16 -16
- package/dist/{performance-R6O3N3UB.js → performance-2N3CFXLR.js} +5 -5
- package/dist/{review-pipeline-MOOWXWSQ.js → review-pipeline-XZIGBU3Q.js} +4 -4
- package/dist/{runtime-RIWQUKBQ.js → runtime-POME3GTR.js} +4 -4
- package/dist/{scan-P7YFKB77.js → scan-IYSVRPD2.js} +1 -1
- package/dist/{security-U76C54W6.js → security-QLJLMSIW.js} +1 -1
- package/dist/{state-events-F44CUUZG.js → state-events-YY5KBZTC.js} +4 -4
- package/dist/{validate-IUAV7MOU.js → validate-VZORVK43.js} +5 -5
- package/dist/{validate-cross-check-M2ZM6RFY.js → validate-cross-check-OYKEDCST.js} +4 -4
- package/package.json +5 -4
- 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
|