@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.
- package/dist/adapters/claude-code.d.ts +5 -10
- package/dist/adapters/claude-code.d.ts.map +1 -1
- package/dist/adapters/claude-code.js +55 -115
- package/dist/adapters/claude-code.js.map +1 -1
- package/dist/adapters/codex.d.ts.map +1 -1
- package/dist/adapters/codex.js +12 -9
- package/dist/adapters/codex.js.map +1 -1
- package/dist/adapters/types.d.ts +3 -1
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/adapters/types.js +15 -13
- package/dist/adapters/types.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +22 -28
- package/dist/commands/init.js.map +1 -1
- package/package.json +1 -1
- package/skills/whyspec-capture/SKILL.md +110 -23
- package/skills/whyspec-debug/SKILL.md +193 -309
- package/skills/whyspec-execute/SKILL.md +123 -31
- package/skills/whyspec-plan/SKILL.md +213 -52
- package/skills/whyspec-search/SKILL.md +88 -20
- package/skills/whyspec-show/SKILL.md +76 -26
|
@@ -1,23 +1,35 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: whyspec-capture
|
|
3
|
-
description:
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
203
|
+
View the full story: /whyspec:show <name>
|
|
143
204
|
```
|
|
144
205
|
|
|
145
|
-
|
|
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.
|
|
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
|
|
241
|
+
- **One context per capture** — each `/whyspec:capture` invocation creates exactly one `ctx_<id>.md` file.
|