@gitwhy-cli/whyspec 0.1.17 → 0.2.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.
@@ -1,23 +1,35 @@
1
1
  ---
2
2
  name: whyspec-capture
3
- description: Capture reasoning after implementationresolve the Decision Bridge by mapping planned decisions to actual outcomes and recording surprises. Use after coding to preserve the WHY behind what was built.
3
+ description: Use after coding to preserve reasoning resolves the Decision Bridge with actual outcomes.
4
+ argument-hint: "[change-name]"
4
5
  ---
5
6
 
6
7
  Capture reasoning — create a context file that resolves the Decision Bridge and preserves the full story.
7
8
 
8
- View the complete story with `/whyspec-show`
9
+ View the complete story with `/whyspec:show`
9
10
 
10
11
  ---
11
12
 
12
13
  **Input**: Optionally specify a change name. If omitted, auto-detect the most recently executed change.
13
14
 
14
- **Steps**
15
+ ## Iron Law
16
+
17
+ **CAPTURE REASONING, NOT SUMMARIES.** "We used Redis" is a summary. "We chose Redis over in-memory because the app runs on 3 instances and rate limits must be shared — in-memory would let users bypass limits by hitting different instances" is reasoning. Every decision needs the WHY.
18
+
19
+ ## Red Flags — If You're Thinking This, STOP
20
+
21
+ - "The implementation was straightforward, not much to capture" → Every implementation has decisions. Find them.
22
+ - "I'll just summarize what files changed" → That's a git log, not reasoning. Capture WHY, not WHAT.
23
+ - "There were no surprises" → Look harder. Did you deviate from the plan at all? Change any approach? That's a surprise.
24
+ - "The decisions are obvious from the code" → They're obvious NOW. In 6 months, they won't be. Write the rationale.
25
+
26
+ ## Steps
15
27
 
16
28
  1. **Select the change**
17
29
 
18
- If a name is provided, use it. Otherwise:
30
+ If ARGUMENTS provides a name, use it. Otherwise:
19
31
  - Auto-detect the most recently executed change (look for changes with completed tasks)
20
- - If ambiguous, run `whyspec list --json` and use **AskUserQuestion** to select
32
+ - If ambiguous, run `whyspec list --json` and let the user select
21
33
 
22
34
  2. **Read plan files for Decision Bridge mapping**
23
35
 
@@ -47,23 +59,78 @@ View the complete story with `/whyspec-show`
47
59
 
48
60
  This is the core of the capture. Map every planned decision to its outcome:
49
61
 
50
- a. **Decisions to Make → Decisions Made**: For EACH checkbox from intent.md's "Decisions to Make", record:
62
+ a. **Decisions to Make → Decisions Made**: For EACH checkbox from intent.md, record:
51
63
  - What was decided
52
64
  - Why (the rationale — not just the choice, but the reasoning)
53
65
  - Any constraints that influenced the decision
54
66
 
55
- b. **Questions to Resolve → Answers**: For EACH question from design.md's "Questions to Resolve", record:
67
+ b. **Questions to Resolve → Answers**: For EACH question from design.md, record:
56
68
  - The answer that emerged during implementation
57
69
  - How it was determined
58
70
 
59
- c. **Capture Surprises**: Identify decisions made during implementation that were NOT in the original plan. Ask yourself:
71
+ c. **Capture Surprises**: Identify decisions made during implementation that were NOT in the original plan:
60
72
  - "What did we decide that we didn't plan to decide?"
61
73
  - "What changed from the original design?"
62
74
  - "What unexpected requirements emerged?"
63
- These surprises are often the most valuable part of the context.
64
75
 
65
76
  If a planned decision was NOT made during implementation, note it as unresolved and ask the user.
66
77
 
78
+ <examples>
79
+ <good>
80
+ ## Decisions Made
81
+
82
+ **Rate limit storage → Redis**
83
+ Chose Redis over in-memory. The app runs on 3 instances behind an ALB.
84
+ In-memory rate limiting would let users bypass limits by hitting different
85
+ instances. Redis adds ~2ms latency per check, but our p99 is already 180ms
86
+ so the overhead is negligible. Reused the existing ioredis client at
87
+ src/lib/redis.ts rather than adding a new dependency.
88
+
89
+ **Limit granularity → Both IP and token**
90
+ IP-only would block shared offices (NAT). Token-only would let unauthenticated
91
+ abuse through. Implemented tiered: 100/15min per IP for unauthenticated,
92
+ 1000/15min per token for authenticated. The token tier uses the JWT sub claim.
93
+
94
+ **429 response → Standard with Retry-After**
95
+ Went with standard 429 + Retry-After header. Custom error body would require
96
+ updating all API clients. The Retry-After header is sufficient for automated
97
+ retry logic and doesn't break existing integrations.
98
+ Why good: Each decision has the WHAT (choice), WHY (rationale), and HOW
99
+ (specific implementation detail). References actual code and numbers.
100
+ </good>
101
+
102
+ <bad>
103
+ ## Decisions Made
104
+ - Used Redis for rate limiting
105
+ - Implemented per-IP and per-token limits
106
+ - Returns 429 status code
107
+ Why bad: Just restates WHAT was done. No WHY. No trade-off reasoning.
108
+ A future developer learns nothing about why these choices were made.
109
+ </bad>
110
+
111
+ <good>
112
+ ## Surprises (not in original plan)
113
+
114
+ **Added X-Request-ID middleware** — During implementation, discovered that
115
+ 429 responses were impossible to debug without a request ID. Added
116
+ X-Request-ID header generation as a prerequisite in src/middleware/requestId.ts.
117
+ This wasn't in the plan but is essential for production debugging.
118
+ Follow-up: Should be extracted into its own WhySpec change if we add more observability.
119
+
120
+ **Changed Redis key schema** — Plan assumed simple key-value, but discovered
121
+ the sliding window algorithm needs sorted sets. Changed from `ratelimit:{ip}`
122
+ string keys to `ratelimit:{ip}` sorted sets with timestamp scores.
123
+ This affects the Redis memory profile — noted in Risks.
124
+ Why good: Documents unplanned decisions with full context. Notes follow-up items.
125
+ </good>
126
+
127
+ <bad>
128
+ (No surprises section)
129
+ Why bad: Every implementation has surprises. If you didn't document any,
130
+ you weren't paying attention.
131
+ </bad>
132
+ </examples>
133
+
67
134
  5. **Generate ctx_<id>.md in SaaS XML format**
68
135
 
69
136
  Write to `<path>/ctx_<id>.md` using the GitWhy SaaS format:
@@ -92,7 +159,6 @@ View the complete story with `/whyspec-show`
92
159
 
93
160
  <decisions>
94
161
  - [Planned decision] — [chosen option] — [rationale]
95
- - [Planned decision] — [chosen option] — [rationale]
96
162
  </decisions>
97
163
 
98
164
  <rejected>
@@ -102,6 +168,9 @@ View the complete story with `/whyspec-show`
102
168
  <tradeoffs>
103
169
  - [Trade-off accepted] — [what was gained vs lost]
104
170
  </tradeoffs>
171
+
172
+ Surprises (decisions not in the original plan):
173
+ - [Unexpected decision] — [why it was needed]
105
174
  </reasoning>
106
175
 
107
176
  <files>
@@ -116,14 +185,6 @@ View the complete story with `/whyspec-show`
116
185
  </context>
117
186
  ```
118
187
 
119
- **Surprises** go in the `<story>` narrative AND as a clearly labeled section in `<reasoning>`:
120
-
121
- ```
122
- Surprises (decisions not in the original plan):
123
- - [Unexpected decision] — [why it was needed]
124
- - [Scope change] — [what triggered it]
125
- ```
126
-
127
188
  6. **Show summary**
128
189
 
129
190
  ```
@@ -139,16 +200,42 @@ View the complete story with `/whyspec-show`
139
200
  Files documented: N
140
201
  Commits linked: N
141
202
 
142
- View the full story: /whyspec-show <name>
203
+ View the full story: /whyspec:show <name>
143
204
  ```
144
205
 
145
- **Guardrails**
206
+ ## Tools
207
+
208
+ | Tool | When to use | When NOT to use |
209
+ |------|------------|-----------------|
210
+ | **Read** | Read intent.md and design.md for Decision Bridge mapping (REQUIRED first step) | Don't skip reading plan files |
211
+ | **Bash** | Run `whyspec capture --json`, `git log --oneline` to find commits, `git diff` to review changes | Don't modify code during capture |
212
+ | **Write** | Create the ctx_<id>.md context file | Don't overwrite existing context files |
213
+ | **Grep** | Search for decisions referenced in plan files (verify they were implemented) | Don't search the entire codebase |
214
+ | **AskUserQuestion** | When a planned decision was NOT made during implementation — ask the user to resolve | Don't ask about decisions that are clearly resolved in the code |
215
+
216
+ ### AskUserQuestion Format (for unresolved decisions only)
217
+
218
+ 1. **Re-ground**: "Capturing reasoning for **<change>**"
219
+ 2. **The gap**: Which planned decision wasn't resolved
220
+ 3. **What you found**: Evidence from the code about what actually happened
221
+ 4. **Ask for rationale**: "What drove this choice?"
222
+
223
+ ## Rationalization Table
224
+
225
+ | If you catch yourself thinking... | Reality |
226
+ |----------------------------------|---------|
227
+ | "This decision is obvious, no need to explain it" | It's obvious now. In 6 months with new team members, it won't be. |
228
+ | "The code is self-documenting" | Code shows WHAT. Context captures WHY. They're complementary. |
229
+ | "There were no surprises during implementation" | You changed zero things from the plan? Really? Look again. |
230
+ | "I'll just list the files that changed" | That's `git diff --stat`. The capture's value is reasoning, not file lists. |
231
+ | "The rationale is already in the commit messages" | Commit messages are 1-2 lines. Reasoning is paragraphs. Different depth. |
232
+
233
+ ## Guardrails
146
234
 
147
235
  - **Must read plan files FIRST** — never generate context without reading intent.md and design.md. The Decision Bridge requires mapping FROM plan TO outcome.
148
236
  - **Every planned decision must be resolved** — if intent.md lists 5 "Decisions to Make", all 5 must appear in the context. Prompt the user for any that weren't addressed.
149
237
  - **Never skip surprises** — unplanned decisions are the most valuable context. Actively search for them.
150
- - **Capture reasoning, not summaries** — write "we chose X because Y outweighs Z in our constraints" not just "we used X." Full reasoning helps future developers understand the choice.
151
238
  - **Use SaaS XML format exactly** — the `<context>` tags must match the GitWhy format so `git why log` and `git why push` work without conversion.
152
- - **Include verification results** — what tests pass, what was manually verified. This grounds the context in evidence.
239
+ - **Include verification results** — what tests pass, what was manually verified. Evidence, not claims.
153
240
  - **Don't fabricate rationale** — if you don't know why a decision was made, ask the user. Invented reasoning is worse than no reasoning.
154
- - **One context per capture** — each `/whyspec-capture` invocation creates exactly one `ctx_<id>.md` file.
241
+ - **One context per capture** — each `/whyspec:capture` invocation creates exactly one `ctx_<id>.md` file.