@popoverai/dotrequirements 0.31.0 → 0.32.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/README.md +26 -9
- package/dist/cli.js +5 -0
- package/dist/commands/create-requirement-document.js +1 -0
- package/dist/commands/greenfield-discovery.d.ts +10 -0
- package/dist/commands/greenfield-discovery.js +13 -0
- package/dist/requirements/greenfield.d.ts +38 -0
- package/dist/requirements/greenfield.js +182 -0
- package/dist/requirements/style-guide.d.ts +10 -2
- package/dist/requirements/style-guide.js +23 -4
- package/dist/templates/context-file-section.md +2 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -44,10 +44,10 @@ Create `*.requirements.md` files in `.requirements/` or colocate them with your
|
|
|
44
44
|
```markdown
|
|
45
45
|
---
|
|
46
46
|
document:
|
|
47
|
-
|
|
47
|
+
defaultPrefix: AUTH-LOGIN
|
|
48
48
|
---
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
# Authentication Requirements
|
|
51
51
|
|
|
52
52
|
```dotrequirements
|
|
53
53
|
AUTH-LOGIN-1: A registered user, Jamie, can log in to their account
|
|
@@ -118,12 +118,28 @@ This shows the team name, prompts you to sign in, adds you to the team, and lets
|
|
|
118
118
|
|
|
119
119
|
### `dotreq link`
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
Connect your local project to the cloud — selecting an existing project, or creating one when the team has room. Opens a browser for authentication, then prints the account it signed in as (`Signed in as you@example.com`).
|
|
122
122
|
|
|
123
123
|
```bash
|
|
124
124
|
dotreq link
|
|
125
|
+
dotreq link --yes --json # non-interactive (for AI assistants/scripts)
|
|
126
|
+
dotreq link --connect my-project # connect to a specific project
|
|
127
|
+
dotreq link --create -n my-api # create a new project with this name
|
|
125
128
|
```
|
|
126
129
|
|
|
130
|
+
**Options:**
|
|
131
|
+
|
|
132
|
+
| Option | Description |
|
|
133
|
+
|--------|-------------|
|
|
134
|
+
| `-y, --yes` | Non-interactive: resolve every decision from defaults or flags; never prompt |
|
|
135
|
+
| `--json` | Machine-readable output (one JSON object on stdout) |
|
|
136
|
+
| `--team <nameOrId>` | Use this team (implies `--yes`) |
|
|
137
|
+
| `--connect <slug>` | Connect to this existing project (implies `--yes`) |
|
|
138
|
+
| `--create` | Create a new project (implies `--yes`) |
|
|
139
|
+
| `-n, --name <name>` | Project name when creating |
|
|
140
|
+
|
|
141
|
+
In non-interactive mode the only human step is completing the browser login. When a genuine choice exists — multiple teams, existing projects, a plan at its project limit — link exits with code `2` and (with `--json`) a `decision_needed` object listing the options, each with the exact flag to retry with where a flag can express it (remedies that happen outside the CLI, like upgrading the team, carry no retry flag). Non-interactive link never syncs the cloud down, so freshly generated local requirements are never overwritten.
|
|
142
|
+
|
|
127
143
|
### `dotreq diff`
|
|
128
144
|
|
|
129
145
|
Show how the repo and the cloud differ, read-only. Each document gets a verdict (in sync, additions in repo, additions in cloud, conflict, only in repo, only in cloud, invalid file).
|
|
@@ -371,9 +387,9 @@ The following features work fully offline—no account required:
|
|
|
371
387
|
|
|
372
388
|
The following features require a dot•requirements cloud account:
|
|
373
389
|
|
|
374
|
-
- Sync requirements (`
|
|
390
|
+
- Sync requirements (`dotreq sync`, `dotreq diff`)
|
|
375
391
|
- Cloud coverage queries (`dotreq report --source cloud`)
|
|
376
|
-
-
|
|
392
|
+
- Hosted style checking and test review (`dotreq style-check --source cloud`, `dotreq review-test --source cloud`)
|
|
377
393
|
- Team collaboration
|
|
378
394
|
|
|
379
395
|
To enable cloud features, run `dotreq link` to connect your project to the cloud.
|
|
@@ -568,12 +584,12 @@ src/components/
|
|
|
568
584
|
```markdown
|
|
569
585
|
---
|
|
570
586
|
document:
|
|
571
|
-
|
|
587
|
+
defaultPrefix: AUTH-LOGIN
|
|
572
588
|
---
|
|
573
589
|
|
|
574
|
-
#
|
|
590
|
+
# Document Title
|
|
575
591
|
|
|
576
|
-
You can include any Markdown
|
|
592
|
+
The leading H1 is the document's title. You can include any Markdown for context.
|
|
577
593
|
|
|
578
594
|
## Requirement Heading
|
|
579
595
|
|
|
@@ -598,7 +614,8 @@ AUTH-LOGIN-2: A user with two-factor auth must provide an OTP
|
|
|
598
614
|
|
|
599
615
|
### Format Details
|
|
600
616
|
|
|
601
|
-
- **Frontmatter**: YAML metadata (
|
|
617
|
+
- **Frontmatter**: YAML metadata (must be present, but no field is required — sync adds `document.id` to link the file to its cloud document)
|
|
618
|
+
- **Title**: The body's leading H1 (a legacy frontmatter `document.title` is tolerated as a fallback)
|
|
602
619
|
- **Headings**: Optional documentation (not parsed as requirement data)
|
|
603
620
|
- **Fenced blocks**: `dotrequirements` blocks contain structured requirement data
|
|
604
621
|
- **First line**: `KEY: content` — the requirement identifier and summary
|
package/dist/cli.js
CHANGED
|
@@ -11,6 +11,7 @@ import { createRequirementDocumentCommand } from "./commands/create-requirement-
|
|
|
11
11
|
import { diffCommand } from "./commands/diff.js";
|
|
12
12
|
import { finalizeCommand } from "./commands/finalize.js";
|
|
13
13
|
import { getCommand } from "./commands/get.js";
|
|
14
|
+
import { greenfieldDiscoveryCommand } from "./commands/greenfield-discovery.js";
|
|
14
15
|
import { initCommand } from "./commands/init.js";
|
|
15
16
|
import { linkCommand } from "./commands/link.js";
|
|
16
17
|
import { listCommand } from "./commands/list.js";
|
|
@@ -206,6 +207,10 @@ program
|
|
|
206
207
|
.command("create-requirement-document [file-path]")
|
|
207
208
|
.description("Print the project style guide; optional [file-path] annotates the output for that target")
|
|
208
209
|
.action(wrapCommand(createRequirementDocumentCommand));
|
|
210
|
+
program
|
|
211
|
+
.command("greenfield-discovery")
|
|
212
|
+
.description("Print the greenfield interview protocol — for working out what something new should do before writing its spec")
|
|
213
|
+
.action(wrapCommand(greenfieldDiscoveryCommand));
|
|
209
214
|
registerCodebaseToSpec(program);
|
|
210
215
|
program.parse();
|
|
211
216
|
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI-GREENFIELD-1: print the greenfield interview protocol for context
|
|
3
|
+
* priming. The protocol interpolates nothing — unlike the style guide there
|
|
4
|
+
* are no project conventions to discover at interview time (those arrive at
|
|
5
|
+
* the writing step, through create-requirement-document) — so this touches
|
|
6
|
+
* neither the workspace nor the cloud, and works before any project is
|
|
7
|
+
* linked (CLI-GREENFIELD-1.3 falls out of there being nothing to fail).
|
|
8
|
+
*/
|
|
9
|
+
export declare function greenfieldDiscoveryCommand(): void;
|
|
10
|
+
//# sourceMappingURL=greenfield-discovery.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { generateGreenfieldProtocol } from "../requirements/greenfield.js";
|
|
2
|
+
/**
|
|
3
|
+
* CLI-GREENFIELD-1: print the greenfield interview protocol for context
|
|
4
|
+
* priming. The protocol interpolates nothing — unlike the style guide there
|
|
5
|
+
* are no project conventions to discover at interview time (those arrive at
|
|
6
|
+
* the writing step, through create-requirement-document) — so this touches
|
|
7
|
+
* neither the workspace nor the cloud, and works before any project is
|
|
8
|
+
* linked (CLI-GREENFIELD-1.3 falls out of there being nothing to fail).
|
|
9
|
+
*/
|
|
10
|
+
export function greenfieldDiscoveryCommand() {
|
|
11
|
+
console.log(generateGreenfieldProtocol({ artifact: "document", formatPointer: true }));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=greenfield-discovery.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Greenfield discovery protocol generator. One module serves the interview to
|
|
3
|
+
* every surface: the CLI verb (`dotreq greenfield-discovery`), the remote MCP
|
|
4
|
+
* tool, and the two web assistants, which import it directly. Kept free of
|
|
5
|
+
* node:fs for exactly that reason, like ./style-guide.ts.
|
|
6
|
+
*
|
|
7
|
+
* The interview's prose is its own spec (ported from the working method — see
|
|
8
|
+
* docs/working/greenfield-discovery.md); this module's *machinery* is specced:
|
|
9
|
+
* CLI-GREENFIELD-1, REMOTE-MCP-13, ASSISTANT-GD-1/2. Content invariants the
|
|
10
|
+
* variants must hold (pointer present or absent, no write mechanics in any
|
|
11
|
+
* ending) are pinned by plain tests in ./greenfield.test.ts.
|
|
12
|
+
*
|
|
13
|
+
* Two facts select the variant, per the settled parameterization: the
|
|
14
|
+
* artifact the interview works toward, and whether the format still needs
|
|
15
|
+
* teaching. The four surfaces are combinations of these two facts — the
|
|
16
|
+
* module knows the differences, not the callers — and no reader ever sees
|
|
17
|
+
* instructions for a surface it is not on.
|
|
18
|
+
*/
|
|
19
|
+
export interface GenerateGreenfieldProtocolParams {
|
|
20
|
+
/** The artifact the interview works toward. `document`: findings are held
|
|
21
|
+
* in the conversation until the gate, and the interview ends by deriving a
|
|
22
|
+
* spec. `board`: findings are recorded onto the discovery board as they
|
|
23
|
+
* land, and the interview ends at the board. */
|
|
24
|
+
artifact: "document" | "board";
|
|
25
|
+
/** Whether to close with the format pointer — the direction to fetch
|
|
26
|
+
* `create-requirement-document` for the format, the project's conventions,
|
|
27
|
+
* and the write steps. On for surfaces nothing has taught the format
|
|
28
|
+
* (the CLI verb, the connector); off for the web assistants, whose system
|
|
29
|
+
* prompts already teach it. */
|
|
30
|
+
formatPointer: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Assemble the interview protocol for a surface, per the two facts that
|
|
34
|
+
* distinguish surfaces. The shared prose is the method itself; only the
|
|
35
|
+
* recording rule, the ending, and the format pointer vary.
|
|
36
|
+
*/
|
|
37
|
+
export declare function generateGreenfieldProtocol(params: GenerateGreenfieldProtocolParams): string;
|
|
38
|
+
//# sourceMappingURL=greenfield.d.ts.map
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Greenfield discovery protocol generator. One module serves the interview to
|
|
3
|
+
* every surface: the CLI verb (`dotreq greenfield-discovery`), the remote MCP
|
|
4
|
+
* tool, and the two web assistants, which import it directly. Kept free of
|
|
5
|
+
* node:fs for exactly that reason, like ./style-guide.ts.
|
|
6
|
+
*
|
|
7
|
+
* The interview's prose is its own spec (ported from the working method — see
|
|
8
|
+
* docs/working/greenfield-discovery.md); this module's *machinery* is specced:
|
|
9
|
+
* CLI-GREENFIELD-1, REMOTE-MCP-13, ASSISTANT-GD-1/2. Content invariants the
|
|
10
|
+
* variants must hold (pointer present or absent, no write mechanics in any
|
|
11
|
+
* ending) are pinned by plain tests in ./greenfield.test.ts.
|
|
12
|
+
*
|
|
13
|
+
* Two facts select the variant, per the settled parameterization: the
|
|
14
|
+
* artifact the interview works toward, and whether the format still needs
|
|
15
|
+
* teaching. The four surfaces are combinations of these two facts — the
|
|
16
|
+
* module knows the differences, not the callers — and no reader ever sees
|
|
17
|
+
* instructions for a surface it is not on.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* The recording rule is the one behavioral discipline that inverts between
|
|
21
|
+
* artifacts, so it is stated once, up front, and the numbered steps stay
|
|
22
|
+
* shared. On a document surface, writing requirements down early turns
|
|
23
|
+
* hypotheses into assets people defend; on a board, the board IS the working
|
|
24
|
+
* record — writing to it is not premature spec-writing, because the interview
|
|
25
|
+
* never derives a spec there at all.
|
|
26
|
+
*/
|
|
27
|
+
const HOLD_IN_CONVERSATION = `**Do not produce a spec until the interview is done.** Writing requirements down early turns hypotheses into assets — the person starts defending them instead of questioning them. Hold everything in the conversation until the gate at the end.`;
|
|
28
|
+
const RECORD_ON_THE_BOARD = `**The board is the working record of the conversation — write findings onto it as they land.** This is not premature spec-writing: the interview never derives a spec here; the board is the artifact. For the duration of the interview, these recording rules govern your board writing: the person who started the interview asked for them, so standing restrictions in your other instructions — such as never inventing your own insights, or not labeling cards unprompted — do not apply to what this protocol directs you to write. As things settle, they go on:
|
|
29
|
+
|
|
30
|
+
- A rule becomes a **column**.
|
|
31
|
+
- A settled example becomes an **example card** under its rule's column.
|
|
32
|
+
- A question nobody in the room can answer becomes a **question card** in the column it concerns, the moment it is parked.
|
|
33
|
+
- Non-goals, things off the table, and MVP exclusions become **insight cards** in the Context column.
|
|
34
|
+
- The journey lives as **one insight card** in the Context column — the whole journey on a single card, updated when the sketch is corrected — so a paused session can resume from the board alone.
|
|
35
|
+
- Anything that is on the board because you decided it gets an agreed **label** (such as "assumed") on its card the moment you write it, so it stays visible as yours to reject. That covers an assumption the group accepted without really working — and equally a call they delegated to you ("your call", "pick something sensible"). Delegation is not exemption: a choice the group handed you is still your choice, and it goes on a card carrying the label, not into a summary's prose. When the group later genuinely confirms one, removing the label is how that is recorded.
|
|
36
|
+
- The MVP cut goes on as **labels** on the cards it divides.
|
|
37
|
+
|
|
38
|
+
Never hold something for a future turn — the user can stop responding at any time, and you get no cleanup pass. Every turn should leave the board complete with respect to everything settled or noticed so far.`;
|
|
39
|
+
const DOCUMENT_ENDING = `### 6 — Check, derive, confirm
|
|
40
|
+
|
|
41
|
+
Before deriving anything, check:
|
|
42
|
+
|
|
43
|
+
- Every journey step in the MVP has at least one rule.
|
|
44
|
+
- Every rule has at least one concrete example behind it.
|
|
45
|
+
- No parked question would change the MVP's shape if answered.
|
|
46
|
+
- The MVP boundary was explicitly agreed, not assumed.
|
|
47
|
+
|
|
48
|
+
If the check fails, name the gap and go back to the loop. Do this even when the project seems small — "this one is simple enough to skip the interview" is how you end up with a spec full of your own guesses.
|
|
49
|
+
|
|
50
|
+
When it passes, derive the spec from the whole conversation and present it as one reviewable proposal:
|
|
51
|
+
|
|
52
|
+
- The requirements, each traceable to the examples that produced it.
|
|
53
|
+
- **Explicitly separated: what they told you versus what you inferred.** If you proposed something and they didn't object, that is not the same as them saying it — and a call they delegated to you ("your call", "pick something sensible") is yours, not theirs. Mark both as yours so they can reject them.
|
|
54
|
+
- What was excluded from the MVP, and why.
|
|
55
|
+
- What is still open.
|
|
56
|
+
|
|
57
|
+
Only after they confirm, write the spec.`;
|
|
58
|
+
const BOARD_ENDING = `### 6 — Check, and leave the board complete
|
|
59
|
+
|
|
60
|
+
When the spine looks done — or the group signals wrapping up — run the check:
|
|
61
|
+
|
|
62
|
+
- Every journey step in the MVP has at least one rule.
|
|
63
|
+
- Every rule has at least one concrete example behind it.
|
|
64
|
+
- No open question card would change the MVP's shape if answered.
|
|
65
|
+
- The MVP boundary was explicitly agreed, not assumed.
|
|
66
|
+
|
|
67
|
+
Present what you find in the same turn you find it, and write any gap you noticed as a question card in the column it concerns as part of presenting it — not after some "end" that may never come. If the group works a gap, the loop resumes and the card is answered or removed in the course of working it. If they never respond again, the cards are already there.
|
|
68
|
+
|
|
69
|
+
When the check passes, say so, play back the journey card and the cut, and stop. The board is the artifact — turning it into a document is a separate act the user reaches for, not this interview's ending.`;
|
|
70
|
+
const FORMAT_POINTER = `Before writing the spec, fetch \`create-requirement-document\` — the verb or tool of that name on your surface — and follow what it returns: the requirements format, this project's own conventions, and the steps for writing. Do not write the spec from memory of the format.`;
|
|
71
|
+
/**
|
|
72
|
+
* Assemble the interview protocol for a surface, per the two facts that
|
|
73
|
+
* distinguish surfaces. The shared prose is the method itself; only the
|
|
74
|
+
* recording rule, the ending, and the format pointer vary.
|
|
75
|
+
*/
|
|
76
|
+
export function generateGreenfieldProtocol(params) {
|
|
77
|
+
const { artifact, formatPointer } = params;
|
|
78
|
+
const recordingRule = artifact === "board" ? RECORD_ON_THE_BOARD : HOLD_IN_CONVERSATION;
|
|
79
|
+
const ending = artifact === "board" ? BOARD_ENDING : DOCUMENT_ENDING;
|
|
80
|
+
const pointer = formatPointer && artifact === "document" ? `\n\n${FORMAT_POINTER}` : "";
|
|
81
|
+
return `# Greenfield discovery
|
|
82
|
+
|
|
83
|
+
Most requirements tools generate a document from a paragraph. This one runs an interview and derives the spec at the end.
|
|
84
|
+
|
|
85
|
+
The person you are talking to usually knows their domain far better than you do and has not yet worked out what they actually want. Your job is to help them find out — by proposing concrete situations and letting them react — not to write plausible-sounding requirements on their behalf.
|
|
86
|
+
|
|
87
|
+
## How to behave throughout
|
|
88
|
+
|
|
89
|
+
**Ask one question per turn.** Batched questions get skimmed and answered shallowly, and they hide which answer mattered.
|
|
90
|
+
|
|
91
|
+
**Never answer your own question to keep moving.** If you fill in an answer because it seemed obvious, you have replaced the person's product with your guess, and neither of you will notice until it ships. When you genuinely need to proceed without an answer, say what you are assuming.
|
|
92
|
+
|
|
93
|
+
**Offer options that aren't obvious.** Two to four concrete alternatives plus room to say something else. If they have already considered everything you offered, the question hasn't done any work.
|
|
94
|
+
|
|
95
|
+
**Propose examples; let them judge.** Asking "what are the rules here?" makes the person do abstraction on the spot, which they will do badly. Describing a specific situation and asking whether it should work lets them answer instantly and correctly.
|
|
96
|
+
|
|
97
|
+
**Never change scope silently, in either direction.** Cutting something and adding something are both decisions the person makes out loud. A silent cut looks like agreement, so nobody challenges it; a silent addition arrives looking like something they asked for, and it survives into the spec unexamined. When you think something belongs in or out, propose it and say plainly that it was your idea.
|
|
98
|
+
|
|
99
|
+
${recordingRule}
|
|
100
|
+
|
|
101
|
+
## The interview
|
|
102
|
+
|
|
103
|
+
### 0 — Offer a way in
|
|
104
|
+
|
|
105
|
+
Ask how they want to work:
|
|
106
|
+
|
|
107
|
+
- **Guided** — one question at a time, from a blank page.
|
|
108
|
+
- **Context dump** — they share what they have, you interview around the gaps.
|
|
109
|
+
- **Best guess** — you draft from what little you have and they correct you.
|
|
110
|
+
|
|
111
|
+
If they pick best guess, be conspicuous about every assumption you made, so they have something specific to push against.
|
|
112
|
+
|
|
113
|
+
### 1 — Establish the frame
|
|
114
|
+
|
|
115
|
+
Before probing anything, get:
|
|
116
|
+
|
|
117
|
+
- The outcome. What changes in the world if this works? Not the feature — the effect.
|
|
118
|
+
- The primary actor. One person whose behavior must change. Others come later.
|
|
119
|
+
- The known non-goals. What do they already know they aren't doing? Offer candidates rather than waiting — "I'd guess this doesn't need to handle team accounts, right?" — because most people haven't articulated the boundary until somebody proposes one to argue with.
|
|
120
|
+
- What is off the table for other reasons. Systems they have to live with, technologies they won't use, approaches they've already tried and abandoned, things they won't build on principle. These cut off whole branches of the interview, so finding them now saves you asking a dozen questions about a direction that was never available.
|
|
121
|
+
|
|
122
|
+
This takes three or four exchanges. Skipping it is the most common failure mode of interview agents — they start interrogating details before knowing what the thing is for.
|
|
123
|
+
|
|
124
|
+
### 2 — Sketch the journey
|
|
125
|
+
|
|
126
|
+
Walk the primary actor from start to outcome, step by step, staying shallow. Ask "then what happens?" repeatedly. Play the sequence back in their own vocabulary and let them correct it.
|
|
127
|
+
|
|
128
|
+
Do not go deep on any step yet — you need the whole shape before you can tell which step deserves the depth.
|
|
129
|
+
|
|
130
|
+
### 3 — Find the risky part
|
|
131
|
+
|
|
132
|
+
Ask which step they are least sure will work. Not the first step — the one that could sink the whole thing. Start the deep work there, because if that step doesn't hold up, the requirements for everything downstream are wasted effort.
|
|
133
|
+
|
|
134
|
+
### 4 — Work the example loop
|
|
135
|
+
|
|
136
|
+
This is the core of the method. For the step under examination, repeat:
|
|
137
|
+
|
|
138
|
+
**Propose a specific situation.** Concrete names, numbers, timing, state. "A customer whose card expired yesterday tries to renew on the last day of their cycle — does that go through?"
|
|
139
|
+
|
|
140
|
+
**Take the verdict.** Yes, no, or "it depends." Yes and no each give you a rule. "It depends" is the best answer available — it means there is a hidden condition, so ask what it depends on and you will get two more examples.
|
|
141
|
+
|
|
142
|
+
**Say the rule back.** State the general rule their answer implies and let them correct it. This is where the person discovers they meant something slightly different from what they said.
|
|
143
|
+
|
|
144
|
+
**Then go looking for trouble.** Vary one dimension at a time: boundaries, empty and enormous, wrong order, interruption partway, two people at once, the actor who shouldn't be allowed. Each variation is another proposed example.
|
|
145
|
+
|
|
146
|
+
Two things run alongside the loop:
|
|
147
|
+
|
|
148
|
+
**Convert vague words as they appear.** "Fast," "easy," "secure," "obvious," "clean" are all placeholders. Ask what would count. If they can't say yet, park it rather than inventing a number.
|
|
149
|
+
|
|
150
|
+
**Park what nobody can answer.** Some questions need a stakeholder who isn't in the room. Note them and move on — blocking on an unanswerable question stalls the interview.
|
|
151
|
+
|
|
152
|
+
**Know when to stop.** Edge cases are endless and most of them don't matter. Once the spine holds — the main path plus the rules that shape it — stop hunting and offer to assume the rest: "I'd assume an expired card just gets declined with a retry prompt rather than cancelling the subscription outright. Reasonable?" An assumption they can reject in one word buys more than four more questions would, and anything they accept — or delegate to you outright — gets marked as yours so it stays visible.
|
|
153
|
+
|
|
154
|
+
Move to the next journey step when the spine has rules with examples behind it, the remaining edges are either settled or explicitly assumed, and no open question would change the step's shape.
|
|
155
|
+
|
|
156
|
+
### 5 — Cut to an MVP, out loud
|
|
157
|
+
|
|
158
|
+
With the journey mapped and the risky part understood, cut:
|
|
159
|
+
|
|
160
|
+
- What is the thinnest end-to-end version that still proves the risky part works?
|
|
161
|
+
- What is deliberately excluded? Add it to the non-goals from step 1 rather than restating them, so there is one list at the end.
|
|
162
|
+
- What survives the cut but with less: fewer variations, one platform, one data case, manual where automatic could come later?
|
|
163
|
+
|
|
164
|
+
Most people cut too little on the first pass, because everything they described feels load-bearing to them. If their MVP still contains nearly everything from the journey, push once — ask what they would drop if they had to ship in a third of the time. Push before they commit to the cut, not after.
|
|
165
|
+
|
|
166
|
+
Every cut is a proposal they approve, never something you apply and mention afterward. The same goes for anything you think should be added.
|
|
167
|
+
|
|
168
|
+
${ending}${pointer}
|
|
169
|
+
|
|
170
|
+
## Things that go wrong
|
|
171
|
+
|
|
172
|
+
**Turning into a questionnaire.** If your questions could have been written before the conversation started, they aren't doing any work. Each question should visibly build on the last answer.
|
|
173
|
+
|
|
174
|
+
**Interviewing about architecture.** Databases, frameworks, and deployment are not behavior. If the conversation drifts technical, come back to what the actor experiences.
|
|
175
|
+
|
|
176
|
+
**Accepting an abstraction.** When someone answers a proposed example with a general policy, thank them and propose another example that tests its edge. Policies stated in the abstract are usually wrong at the boundaries.
|
|
177
|
+
|
|
178
|
+
**Being agreeable.** If they assert something that contradicts an earlier answer, or that reopens something they put off the table at the start, say so plainly and ask which one holds.
|
|
179
|
+
|
|
180
|
+
**Finishing early because they seem done.** People stop talking when they run out of things they have already thought about. Keep going.`;
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=greenfield.js.map
|
|
@@ -33,12 +33,20 @@ export interface GenerateStyleGuideParams {
|
|
|
33
33
|
* `requirementsStyleContext` field). Pass null/undefined to omit. */
|
|
34
34
|
customStyleGuidance?: string | null;
|
|
35
35
|
/** Suggested target path for the new file. Used only in the preamble and
|
|
36
|
-
* "Next Steps" section. Defaults to a generic example path.
|
|
36
|
+
* "Next Steps" section. Defaults to a generic example path. Workspace
|
|
37
|
+
* surface only — the connector variant names no file path. */
|
|
37
38
|
filePath?: string;
|
|
38
39
|
/** Project-local STYLE.md contents. When provided and non-empty, this body
|
|
39
40
|
* replaces the bundled default. CLI-only — see `readLocalStyleGuide` in
|
|
40
41
|
* ./style-guide-file.ts. */
|
|
41
42
|
localStyleGuide?: string | null;
|
|
43
|
+
/** How specs are written where this guide is going. The conventions body is
|
|
44
|
+
* identical either way (REMOTE-MCP-10.5); only the framing and "Next Steps"
|
|
45
|
+
* differ. `workspace` (the default) frames the template as a file to save
|
|
46
|
+
* and closes with the repo workflow (CLI-CREATE-DOC-1.8); `connector`
|
|
47
|
+
* frames it as document content to compose and closes with the connector's
|
|
48
|
+
* own tools — no file paths, no CLI commands (REMOTE-MCP-10.9/10.10). */
|
|
49
|
+
surface?: "workspace" | "connector";
|
|
42
50
|
}
|
|
43
51
|
/**
|
|
44
52
|
* Build the body of the bundled default style guide. This is the content
|
|
@@ -51,7 +59,7 @@ export interface GenerateStyleGuideParams {
|
|
|
51
59
|
* - swap the body wholesale (via `localStyleGuide`) without losing the
|
|
52
60
|
* wrapping preamble + "Next Steps" footer
|
|
53
61
|
*/
|
|
54
|
-
export declare function generateStyleGuideBody(params: Omit<GenerateStyleGuideParams, "filePath" | "localStyleGuide">): string;
|
|
62
|
+
export declare function generateStyleGuideBody(params: Omit<GenerateStyleGuideParams, "filePath" | "localStyleGuide" | "surface">): string;
|
|
55
63
|
/**
|
|
56
64
|
* Build a complete style-guide document for the calling workspace.
|
|
57
65
|
* Returns a single markdown string suitable for printing to stdout or
|
|
@@ -297,10 +297,29 @@ describe(requirement('AUTH-LOGIN-1'), () => {
|
|
|
297
297
|
* always applied.
|
|
298
298
|
*/
|
|
299
299
|
export function generateStyleGuide(params) {
|
|
300
|
-
const { filePath = ".requirements/example.requirements.md", localStyleGuide, } = params;
|
|
300
|
+
const { filePath = ".requirements/example.requirements.md", localStyleGuide, surface = "workspace", } = params;
|
|
301
301
|
const body = localStyleGuide?.trim()
|
|
302
302
|
? localStyleGuide
|
|
303
303
|
: generateStyleGuideBody(params);
|
|
304
|
+
// REMOTE-MCP-10.9/10.10: the connector variant frames the template as
|
|
305
|
+
// document content and closes with the connector's own tools. A chat agent
|
|
306
|
+
// has no workspace, so a file path or CLI command here is an instruction
|
|
307
|
+
// it can only relay to someone who cannot follow it either.
|
|
308
|
+
if (surface === "connector") {
|
|
309
|
+
return `# Requirements Document Template
|
|
310
|
+
|
|
311
|
+
Here's a comprehensive template with format and style guidance:
|
|
312
|
+
|
|
313
|
+
\`\`\`markdown
|
|
314
|
+
${body}
|
|
315
|
+
\`\`\`
|
|
316
|
+
|
|
317
|
+
## Next Steps
|
|
318
|
+
|
|
319
|
+
1. **Compose**: Draft the document's full markdown, embedding requirements in \`\`\`dotrequirements blocks
|
|
320
|
+
2. **Refine style** (optional): Pass the drafted markdown to the \`style-check\` tool for feedback before anything is saved
|
|
321
|
+
3. **Create**: Call \`create-document\` with the markdown — creating publishes it to the team`;
|
|
322
|
+
}
|
|
304
323
|
return `# Requirements File Template
|
|
305
324
|
|
|
306
325
|
Here's a comprehensive template for \`${filePath}\` with format and style guidance:
|
|
@@ -312,9 +331,9 @@ ${body}
|
|
|
312
331
|
## Next Steps
|
|
313
332
|
|
|
314
333
|
1. **Create file**: Save this template as \`${filePath}\` and edit it for your feature
|
|
315
|
-
2. **Refine style** (optional): Run \`style-check\` for AI feedback
|
|
316
|
-
3. **Validate syntax**: Run \`validate\` to verify format
|
|
317
|
-
4. **Sync to cloud**: Run \`
|
|
334
|
+
2. **Refine style** (optional): Run \`dotreq style-check\` for AI feedback
|
|
335
|
+
3. **Validate syntax**: Run \`dotreq validate\` to verify format
|
|
336
|
+
4. **Sync to cloud**: Run \`dotreq sync\` to reconcile the repo and the cloud
|
|
318
337
|
|
|
319
338
|
**Note**: Requirements files can be colocated with code (\`src/auth.requirements.md\`) or centralized in \`.requirements/\` directory.`;
|
|
320
339
|
}
|
|
@@ -57,7 +57,8 @@ test(requirement('REQ-ID.0'), () => { /* test specific criterion */ });
|
|
|
57
57
|
|
|
58
58
|
**Authoring:**
|
|
59
59
|
- `dotreq create-requirement-document [path]` - Print the template and style guide
|
|
60
|
-
- `dotreq
|
|
60
|
+
- `dotreq greenfield-discovery` - Print the interview protocol for working out what something new should do. Run it when the user is starting something new and has not worked out what it should do — the interview beats drafting requirements from their description
|
|
61
|
+
- `dotreq validate [--file <path>]` - Check syntax (works offline)
|
|
61
62
|
- `dotreq diff [scope...]` - Show how the repo and the cloud differ (read-only)
|
|
62
63
|
- `dotreq sync [scope...]` - Reconcile the repo and the cloud (both contribute by default)
|
|
63
64
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@popoverai/dotrequirements",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.32.0",
|
|
4
4
|
"description": "Requirements as testable, human-readable data — CLI and test harness for spec-driven development with AI coding agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
"./test": "./dist/harness/index.js",
|
|
13
13
|
"./schema": "./dist/schema/index.js",
|
|
14
14
|
"./schema/browser": "./dist/schema/browser.js",
|
|
15
|
-
"./style-guide": "./dist/requirements/style-guide.js"
|
|
15
|
+
"./style-guide": "./dist/requirements/style-guide.js",
|
|
16
|
+
"./greenfield": "./dist/requirements/greenfield.js"
|
|
16
17
|
},
|
|
17
18
|
"publishConfig": {
|
|
18
19
|
"access": "public"
|