@gitwhy-cli/whyspec 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +113 -0
  3. package/dist/adapters/agents-md.d.ts +13 -0
  4. package/dist/adapters/agents-md.d.ts.map +1 -0
  5. package/dist/adapters/agents-md.js +165 -0
  6. package/dist/adapters/agents-md.js.map +1 -0
  7. package/dist/adapters/claude-code.d.ts +13 -0
  8. package/dist/adapters/claude-code.d.ts.map +1 -0
  9. package/dist/adapters/claude-code.js +206 -0
  10. package/dist/adapters/claude-code.js.map +1 -0
  11. package/dist/adapters/cursor.d.ts +12 -0
  12. package/dist/adapters/cursor.d.ts.map +1 -0
  13. package/dist/adapters/cursor.js +220 -0
  14. package/dist/adapters/cursor.js.map +1 -0
  15. package/dist/adapters/types.d.ts +16 -0
  16. package/dist/adapters/types.d.ts.map +1 -0
  17. package/dist/adapters/types.js +19 -0
  18. package/dist/adapters/types.js.map +1 -0
  19. package/dist/cli/index.d.ts +3 -0
  20. package/dist/cli/index.d.ts.map +1 -0
  21. package/dist/cli/index.js +109 -0
  22. package/dist/cli/index.js.map +1 -0
  23. package/dist/commands/capture.d.ts +18 -0
  24. package/dist/commands/capture.d.ts.map +1 -0
  25. package/dist/commands/capture.js +85 -0
  26. package/dist/commands/capture.js.map +1 -0
  27. package/dist/commands/debug.d.ts +16 -0
  28. package/dist/commands/debug.d.ts.map +1 -0
  29. package/dist/commands/debug.js +74 -0
  30. package/dist/commands/debug.js.map +1 -0
  31. package/dist/commands/execute.d.ts +36 -0
  32. package/dist/commands/execute.d.ts.map +1 -0
  33. package/dist/commands/execute.js +110 -0
  34. package/dist/commands/execute.js.map +1 -0
  35. package/dist/commands/init.d.ts +14 -0
  36. package/dist/commands/init.d.ts.map +1 -0
  37. package/dist/commands/init.js +166 -0
  38. package/dist/commands/init.js.map +1 -0
  39. package/dist/commands/list.d.ts +23 -0
  40. package/dist/commands/list.d.ts.map +1 -0
  41. package/dist/commands/list.js +95 -0
  42. package/dist/commands/list.js.map +1 -0
  43. package/dist/commands/plan.d.ts +20 -0
  44. package/dist/commands/plan.d.ts.map +1 -0
  45. package/dist/commands/plan.js +48 -0
  46. package/dist/commands/plan.js.map +1 -0
  47. package/dist/commands/search.d.ts +12 -0
  48. package/dist/commands/search.d.ts.map +1 -0
  49. package/dist/commands/search.js +36 -0
  50. package/dist/commands/search.js.map +1 -0
  51. package/dist/commands/show.d.ts +25 -0
  52. package/dist/commands/show.d.ts.map +1 -0
  53. package/dist/commands/show.js +145 -0
  54. package/dist/commands/show.js.map +1 -0
  55. package/dist/commands/status.d.ts +29 -0
  56. package/dist/commands/status.d.ts.map +1 -0
  57. package/dist/commands/status.js +125 -0
  58. package/dist/commands/status.js.map +1 -0
  59. package/dist/commands/template.d.ts +14 -0
  60. package/dist/commands/template.d.ts.map +1 -0
  61. package/dist/commands/template.js +25 -0
  62. package/dist/commands/template.js.map +1 -0
  63. package/dist/core/categorize.d.ts +30 -0
  64. package/dist/core/categorize.d.ts.map +1 -0
  65. package/dist/core/categorize.js +72 -0
  66. package/dist/core/categorize.js.map +1 -0
  67. package/dist/core/config.d.ts +26 -0
  68. package/dist/core/config.d.ts.map +1 -0
  69. package/dist/core/config.js +52 -0
  70. package/dist/core/config.js.map +1 -0
  71. package/dist/core/context.d.ts +27 -0
  72. package/dist/core/context.d.ts.map +1 -0
  73. package/dist/core/context.js +75 -0
  74. package/dist/core/context.js.map +1 -0
  75. package/dist/core/search.d.ts +51 -0
  76. package/dist/core/search.d.ts.map +1 -0
  77. package/dist/core/search.js +235 -0
  78. package/dist/core/search.js.map +1 -0
  79. package/dist/core/storage.d.ts +36 -0
  80. package/dist/core/storage.d.ts.map +1 -0
  81. package/dist/core/storage.js +80 -0
  82. package/dist/core/storage.js.map +1 -0
  83. package/dist/core/templates.d.ts +28 -0
  84. package/dist/core/templates.d.ts.map +1 -0
  85. package/dist/core/templates.js +176 -0
  86. package/dist/core/templates.js.map +1 -0
  87. package/dist/ui/ascii-logo.d.ts +7 -0
  88. package/dist/ui/ascii-logo.d.ts.map +1 -0
  89. package/dist/ui/ascii-logo.js +15 -0
  90. package/dist/ui/ascii-logo.js.map +1 -0
  91. package/dist/ui/tool-picker.d.ts +13 -0
  92. package/dist/ui/tool-picker.d.ts.map +1 -0
  93. package/dist/ui/tool-picker.js +76 -0
  94. package/dist/ui/tool-picker.js.map +1 -0
  95. package/dist/ui/welcome.d.ts +4 -0
  96. package/dist/ui/welcome.d.ts.map +1 -0
  97. package/dist/ui/welcome.js +43 -0
  98. package/dist/ui/welcome.js.map +1 -0
  99. package/dist/utils/changes.d.ts +19 -0
  100. package/dist/utils/changes.d.ts.map +1 -0
  101. package/dist/utils/changes.js +63 -0
  102. package/dist/utils/changes.js.map +1 -0
  103. package/dist/utils/git.d.ts +28 -0
  104. package/dist/utils/git.d.ts.map +1 -0
  105. package/dist/utils/git.js +104 -0
  106. package/dist/utils/git.js.map +1 -0
  107. package/dist/utils/slugify.d.ts +12 -0
  108. package/dist/utils/slugify.d.ts.map +1 -0
  109. package/dist/utils/slugify.js +21 -0
  110. package/dist/utils/slugify.js.map +1 -0
  111. package/dist/utils/telemetry.d.ts +21 -0
  112. package/dist/utils/telemetry.d.ts.map +1 -0
  113. package/dist/utils/telemetry.js +32 -0
  114. package/dist/utils/telemetry.js.map +1 -0
  115. package/package.json +81 -0
  116. package/skills/whyspec-capture/SKILL.md +154 -0
  117. package/skills/whyspec-debug/SKILL.md +404 -0
  118. package/skills/whyspec-execute/SKILL.md +118 -0
  119. package/skills/whyspec-plan/SKILL.md +170 -0
  120. package/skills/whyspec-search/SKILL.md +69 -0
  121. package/skills/whyspec-show/SKILL.md +90 -0
@@ -0,0 +1,220 @@
1
+ import { WHYSPEC_COMMANDS, COMMAND_DESCRIPTIONS, } from "./types.js";
2
+ /**
3
+ * Generate the Cursor command instructions for each WhySpec command.
4
+ * Cursor commands are plain markdown — no YAML frontmatter.
5
+ */
6
+ function getCursorCommandContent(command) {
7
+ switch (command) {
8
+ case "plan":
9
+ return `# WhySpec Plan
10
+
11
+ ${COMMAND_DESCRIPTIONS.plan}
12
+
13
+ ## Objective
14
+
15
+ Create a structured plan before coding — capturing intent, design decisions to make, and implementation tasks. This is the BEFORE side of the Decision Bridge.
16
+
17
+ ## Workflow
18
+
19
+ 1. Ask the developer 2-3 forcing questions:
20
+ - "What problem does this solve?"
21
+ - "What constraints exist?"
22
+ - "How will you know it works?"
23
+
24
+ 2. Call the WhySpec CLI to create the change folder:
25
+ \`\`\`bash
26
+ whyspec plan --json "<change-name>"
27
+ \`\`\`
28
+
29
+ 3. Parse the JSON response to get the folder path and templates.
30
+
31
+ 4. Create three files in the change folder:
32
+ - **intent.md** — Why this change exists, decisions to make, constraints, success criteria
33
+ - **design.md** — Technical approach, trade-off matrix, architecture, questions to resolve
34
+ - **tasks.md** — Verification criteria (defined FIRST), then implementation checklist
35
+
36
+ 5. Each decision-to-make should be a checkbox: \`- [ ] Token storage: cookie vs localStorage?\`
37
+
38
+ ## Important
39
+
40
+ - Always call the CLI first — it handles path creation and validation.
41
+ - Capture COMPLETE reasoning, not abbreviated summaries.
42
+ - The "Decisions to Make" section in design.md is the BEFORE side of the Decision Bridge.`;
43
+ case "execute":
44
+ return `# WhySpec Execute
45
+
46
+ ${COMMAND_DESCRIPTIONS.execute}
47
+
48
+ ## Objective
49
+
50
+ Implement a planned change using the plan files as context. Track progress through the task list and commit atomically.
51
+
52
+ ## Workflow
53
+
54
+ 1. Call the WhySpec CLI to get execution context:
55
+ \`\`\`bash
56
+ whyspec execute --json "<change-name>"
57
+ \`\`\`
58
+
59
+ 2. Parse the JSON response to get intent, design, tasks, and progress.
60
+
61
+ 3. Read intent.md and design.md for WHY context — understand the goal before coding.
62
+
63
+ 4. Work through tasks.md sequentially:
64
+ - Show progress: "Working on task 3/7: <description>"
65
+ - Implement the code changes
66
+ - Mark each task complete: \`- [ ]\` → \`- [x]\` in tasks.md
67
+ - Commit atomically (one commit per task or logical unit)
68
+
69
+ 5. On completion, prompt: "Ready to capture reasoning? Run /whyspec-capture"
70
+
71
+ ## Important
72
+
73
+ - Use intent.md as context while implementing — it contains the WHY.
74
+ - Track deviations from the plan — surprises are valuable for capture.
75
+ - Do not skip tasks or mark them done without implementing.`;
76
+ case "capture":
77
+ return `# WhySpec Capture
78
+
79
+ ${COMMAND_DESCRIPTIONS.capture}
80
+
81
+ ## Objective
82
+
83
+ After coding, capture the reasoning behind what was built — completing the Decision Bridge by recording which decisions were made and why.
84
+
85
+ ## Workflow
86
+
87
+ 1. Call the WhySpec CLI to get the capture template:
88
+ \`\`\`bash
89
+ whyspec capture --json "<change-name>"
90
+ \`\`\`
91
+
92
+ 2. Parse the JSON response to get the template, linked commits, and files changed.
93
+
94
+ 3. Read intent.md and design.md from the change folder.
95
+
96
+ 4. Create a context file with:
97
+ - Map each "Decision to Make" from design.md → "Decisions Made" with rationale
98
+ - Map each "Question to Resolve" → resolved answer
99
+ - Capture "Surprises" — decisions NOT in the plan
100
+ - Include story, rejected alternatives, trade-offs, verification, risks
101
+
102
+ ## Important
103
+
104
+ - Include ALL decisions, not just the ones from the plan.
105
+ - Surprises (unplanned decisions) are the most valuable part of the capture.
106
+ - This completes the Decision Bridge: plan PREDICTED decisions, capture RECORDS them.`;
107
+ case "show":
108
+ return `# WhySpec Show
109
+
110
+ ${COMMAND_DESCRIPTIONS.show}
111
+
112
+ ## Objective
113
+
114
+ Display the full story of a change — from intent through design, tasks, and captured reasoning — with the Decision Bridge delta highlighted.
115
+
116
+ ## Workflow
117
+
118
+ 1. Call the WhySpec CLI to get the full change data:
119
+ \`\`\`bash
120
+ whyspec show --json "<change-name>"
121
+ \`\`\`
122
+
123
+ 2. Parse the JSON response containing intent, design, tasks, context, and Decision Bridge delta.
124
+
125
+ 3. Display the change story in sections:
126
+ - **Intent** — WHY (from intent.md)
127
+ - **Design** — HOW (from design.md)
128
+ - **Tasks** — WHAT (from tasks.md with completion status)
129
+ - **Context** — REASONING (from captured context)
130
+ - **Decision Bridge Delta** — Decisions to Make vs Decisions Made
131
+
132
+ ## Important
133
+
134
+ - The Decision Bridge delta is the unique value — always show it.
135
+ - If context hasn't been captured yet, show intent + design + tasks and suggest running /whyspec-capture.`;
136
+ case "search":
137
+ return `# WhySpec Search
138
+
139
+ ${COMMAND_DESCRIPTIONS.search}
140
+
141
+ ## Objective
142
+
143
+ Find past decisions and reasoning across all changes — building institutional knowledge that improves future work.
144
+
145
+ ## Workflow
146
+
147
+ 1. Call the WhySpec CLI to search:
148
+ \`\`\`bash
149
+ whyspec search --json "<query>"
150
+ \`\`\`
151
+
152
+ 2. Parse the JSON response containing scored results with snippets.
153
+
154
+ 3. Display results ranked by relevance:
155
+ - Title matches score highest (100 points)
156
+ - Reasoning/decision matches score next (30 points)
157
+ - File path matches score lower (20 points)
158
+
159
+ 4. For each result, show: title, change name, score, and a relevant snippet.
160
+
161
+ ## Important
162
+
163
+ - Search covers both active changes and archived ones.
164
+ - Search also finds intent.md and design.md — not just captured contexts.
165
+ - Use this before starting new work: "Has anyone reasoned about this area before?"`;
166
+ case "debug":
167
+ return `# WhySpec Debug
168
+
169
+ ${COMMAND_DESCRIPTIONS.debug}
170
+
171
+ ## Objective
172
+
173
+ Investigate a bug using the scientific method — capturing symptoms, hypotheses, evidence, root cause, fix, and prevention. Searches past decisions for related context.
174
+
175
+ ## Workflow
176
+
177
+ 1. Call the WhySpec CLI to create a debug session:
178
+ \`\`\`bash
179
+ whyspec debug --json "<bug-description>"
180
+ \`\`\`
181
+
182
+ 2. Parse the JSON response to get the debug folder path and related past contexts.
183
+
184
+ 3. Follow the scientific method:
185
+ - **Symptoms** — Expected vs actual behavior, error messages, reproduction steps
186
+ - **Related contexts** — Check past decisions in this area (from CLI response)
187
+ - **Hypotheses** — Form 3+ falsifiable hypotheses with "what would prove this wrong?"
188
+ - **Investigation** — Test each hypothesis with evidence gathering
189
+ - **Root cause** — Prove the diagnosis BEFORE proposing a fix (Iron Law)
190
+ - **Fix** — Apply the fix and verify
191
+ - **Prevention** — How to prevent this class of bug in the future
192
+
193
+ 4. Create debug.md with the full investigation trail.
194
+
195
+ 5. On completion, prompt: "Ready to capture debug reasoning? Run /whyspec-capture"
196
+
197
+ ## Important
198
+
199
+ - No fix without root cause — this is the Iron Law.
200
+ - Check related past contexts BEFORE forming hypotheses.
201
+ - The debug.md persists across sessions so investigation survives context resets.`;
202
+ }
203
+ }
204
+ /**
205
+ * Generate Cursor custom slash command files for all 6 WhySpec commands.
206
+ *
207
+ * Creates .cursor/commands/whyspec-<command>.md files — plain markdown
208
+ * that Cursor discovers automatically as slash commands.
209
+ *
210
+ * @param projectRoot - Optional project root prefix for paths (default: "")
211
+ * @returns Array of GeneratedFile objects
212
+ */
213
+ export function generateCursorCommands(projectRoot = "") {
214
+ const prefix = projectRoot ? `${projectRoot}/` : "";
215
+ return WHYSPEC_COMMANDS.map((command) => ({
216
+ path: `${prefix}.cursor/commands/whyspec-${command}.md`,
217
+ content: getCursorCommandContent(command) + "\n",
218
+ }));
219
+ }
220
+ //# sourceMappingURL=cursor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/adapters/cursor.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,gBAAgB,EAChB,oBAAoB,GAErB,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,SAAS,uBAAuB,CAAC,OAAuB;IACtD,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,MAAM;YACT,OAAO;;EAEX,oBAAoB,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0FA+B+D,CAAC;QAEvF,KAAK,SAAS;YACZ,OAAO;;EAEX,oBAAoB,CAAC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4DA6B8B,CAAC;QAEzD,KAAK,SAAS;YACZ,OAAO;;EAEX,oBAAoB,CAAC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;sFA2BwD,CAAC;QAEnF,KAAK,MAAM;YACT,OAAO;;EAEX,oBAAoB,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;0GAyB+E,CAAC;QAEvG,KAAK,QAAQ;YACX,OAAO;;EAEX,oBAAoB,CAAC,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;mFA0BsD,CAAC;QAEhF,KAAK,OAAO;YACV,OAAO;;EAEX,oBAAoB,CAAC,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kFAgCsD,CAAC;IACjF,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CACpC,cAAsB,EAAE;IAExB,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAEpD,OAAO,gBAAgB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACxC,IAAI,EAAE,GAAG,MAAM,4BAA4B,OAAO,KAAK;QACvD,OAAO,EAAE,uBAAuB,CAAC,OAAO,CAAC,GAAG,IAAI;KACjD,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * A file to be generated by an adapter.
3
+ * Adapters return these; the caller handles writing to disk.
4
+ */
5
+ export interface GeneratedFile {
6
+ /** Relative path from project root (e.g., ".claude/skills/whyspec-plan/SKILL.md") */
7
+ path: string;
8
+ /** File content */
9
+ content: string;
10
+ }
11
+ /** The 6 WhySpec commands that adapters generate config for. */
12
+ export declare const WHYSPEC_COMMANDS: readonly ["plan", "execute", "capture", "show", "search", "debug"];
13
+ export type WhySpecCommand = (typeof WHYSPEC_COMMANDS)[number];
14
+ /** One-line descriptions for each command, used across all adapters. */
15
+ export declare const COMMAND_DESCRIPTIONS: Record<WhySpecCommand, string>;
16
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/adapters/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,qFAAqF;IACrF,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,gEAAgE;AAChE,eAAO,MAAM,gBAAgB,oEAOnB,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/D,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAO/D,CAAC"}
@@ -0,0 +1,19 @@
1
+ /** The 6 WhySpec commands that adapters generate config for. */
2
+ export const WHYSPEC_COMMANDS = [
3
+ "plan",
4
+ "execute",
5
+ "capture",
6
+ "show",
7
+ "search",
8
+ "debug",
9
+ ];
10
+ /** One-line descriptions for each command, used across all adapters. */
11
+ export const COMMAND_DESCRIPTIONS = {
12
+ plan: "Declare intent and plan decisions before coding",
13
+ execute: "Implement from plan with full reasoning context",
14
+ capture: "Save the reasoning behind what was built",
15
+ show: "View the full story of a change with Decision Bridge delta",
16
+ search: "Search past decisions and reasoning across all changes",
17
+ debug: "Debug with the scientific method and capture root cause",
18
+ };
19
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/adapters/types.ts"],"names":[],"mappings":"AAWA,gEAAgE;AAChE,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,MAAM;IACN,SAAS;IACT,SAAS;IACT,MAAM;IACN,QAAQ;IACR,OAAO;CACC,CAAC;AAIX,wEAAwE;AACxE,MAAM,CAAC,MAAM,oBAAoB,GAAmC;IAClE,IAAI,EAAE,iDAAiD;IACvD,OAAO,EAAE,iDAAiD;IAC1D,OAAO,EAAE,0CAA0C;IACnD,IAAI,EAAE,4DAA4D;IAClE,MAAM,EAAE,wDAAwD;IAChE,KAAK,EAAE,yDAAyD;CACjE,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { runInit } from "../commands/init.js";
4
+ import { planCommand } from "../commands/plan.js";
5
+ import { executeCommand } from "../commands/execute.js";
6
+ import { captureCommand } from "../commands/capture.js";
7
+ import { showCommand } from "../commands/show.js";
8
+ import { searchCommand } from "../commands/search.js";
9
+ import { debugCommand } from "../commands/debug.js";
10
+ import { listCommand } from "../commands/list.js";
11
+ import { statusCommand } from "../commands/status.js";
12
+ import { templateCommand } from "../commands/template.js";
13
+ const program = new Command();
14
+ program
15
+ .name("whyspec")
16
+ .description("The reasoning layer for AI-assisted development — capture WHY code was built the way it was")
17
+ .version("0.1.0")
18
+ .option("--json", "Output structured JSON for agent consumption");
19
+ // ── init ────────────────────────────────────────────────────────────────────
20
+ program
21
+ .command("init")
22
+ .description("Initialize WhySpec in the current project")
23
+ .action(async () => {
24
+ await runInit();
25
+ });
26
+ // ── plan ────────────────────────────────────────────────────────────────────
27
+ program
28
+ .command("plan")
29
+ .description("Create a change folder with intent, design, and task templates")
30
+ .argument("[name]", "Name of the change (e.g., add-jwt-auth)")
31
+ .action(async (name, _opts, cmd) => {
32
+ const json = cmd.optsWithGlobals().json;
33
+ await planCommand(name, { json });
34
+ });
35
+ // ── execute ─────────────────────────────────────────────────────────────────
36
+ program
37
+ .command("execute")
38
+ .description("Get execution context from a plan (intent + design + tasks)")
39
+ .argument("[name]", "Name of the change to execute")
40
+ .action(async (name, _opts, cmd) => {
41
+ const json = cmd.optsWithGlobals().json;
42
+ await executeCommand(name, { json });
43
+ });
44
+ // ── capture ─────────────────────────────────────────────────────────────────
45
+ program
46
+ .command("capture")
47
+ .description("Capture reasoning after implementation (creates ctx_<id>.md)")
48
+ .argument("[name]", "Name of the change to capture")
49
+ .action(async (name, _opts, cmd) => {
50
+ const json = cmd.optsWithGlobals().json;
51
+ await captureCommand(name, { json });
52
+ });
53
+ // ── show ────────────────────────────────────────────────────────────────────
54
+ program
55
+ .command("show")
56
+ .description("Display the full story of a change with Decision Bridge delta")
57
+ .argument("<name>", "Name of the change to show")
58
+ .action(async (name, _opts, cmd) => {
59
+ const json = cmd.optsWithGlobals().json;
60
+ await showCommand(name, { json });
61
+ });
62
+ // ── search ──────────────────────────────────────────────────────────────────
63
+ program
64
+ .command("search")
65
+ .description("Search past decisions and reasoning across all changes")
66
+ .argument("<query>", "Search query")
67
+ .option("--domain <domain>", "Filter by domain")
68
+ .option("--limit <n>", "Maximum results", "10")
69
+ .action(async (query, opts, cmd) => {
70
+ const json = cmd.optsWithGlobals().json;
71
+ await searchCommand(query, { json, domain: opts.domain, limit: opts.limit });
72
+ });
73
+ // ── debug ───────────────────────────────────────────────────────────────────
74
+ program
75
+ .command("debug")
76
+ .description("Create a structured debug session (scientific method)")
77
+ .argument("[name]", "Name or description of the bug")
78
+ .action(async (name, _opts, cmd) => {
79
+ const json = cmd.optsWithGlobals().json;
80
+ await debugCommand(name, { json });
81
+ });
82
+ // ── list ────────────────────────────────────────────────────────────────────
83
+ program
84
+ .command("list")
85
+ .description("List all active changes with status")
86
+ .action(async (_opts, cmd) => {
87
+ const json = cmd.optsWithGlobals().json;
88
+ await listCommand({ json });
89
+ });
90
+ // ── status ──────────────────────────────────────────────────────────────────
91
+ program
92
+ .command("status")
93
+ .description("Get detailed status for a change")
94
+ .argument("<name>", "Name of the change")
95
+ .action(async (name, _opts, cmd) => {
96
+ const json = cmd.optsWithGlobals().json;
97
+ await statusCommand(name, { json });
98
+ });
99
+ // ── template ────────────────────────────────────────────────────────────────
100
+ program
101
+ .command("template")
102
+ .description("Get a raw file template (intent, design, tasks, context, debug)")
103
+ .argument("<type>", "Template type: intent | design | tasks | context | debug")
104
+ .action(async (type, _opts, cmd) => {
105
+ const json = cmd.optsWithGlobals().json;
106
+ await templateCommand(type, { json });
107
+ });
108
+ program.parse();
109
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * whyspec capture — Capture reasoning context for a change.
3
+ *
4
+ * --json mode: returns XML template + commits + files + Decision Bridge data.
5
+ * Non-JSON mode: writes ctx_<id>.md with metadata header + XML template.
6
+ */
7
+ export interface CaptureJsonOutput {
8
+ template: string;
9
+ commits: string[];
10
+ files_changed: string[];
11
+ decisions_to_make: string[];
12
+ change_name: string;
13
+ change_path: string;
14
+ }
15
+ export declare function captureCommand(name: string | undefined, options: {
16
+ json?: boolean;
17
+ }): Promise<void>;
18
+ //# sourceMappingURL=capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/commands/capture.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAcH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAOD,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CA0Ef"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * whyspec capture — Capture reasoning context for a change.
3
+ *
4
+ * --json mode: returns XML template + commits + files + Decision Bridge data.
5
+ * Non-JSON mode: writes ctx_<id>.md with metadata header + XML template.
6
+ */
7
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
8
+ import { join } from "node:path";
9
+ import chalk from "chalk";
10
+ import { resolveChange } from "../utils/changes.js";
11
+ import { getCurrentBranch, getCommitsSince, getFilesChanged, getRemoteUrl } from "../utils/git.js";
12
+ import { generateContextId, renderContextXml, extractDecisions, getChangeFolderCreatedAt, } from "../core/context.js";
13
+ function readFileOrEmpty(filePath) {
14
+ if (!existsSync(filePath))
15
+ return "";
16
+ return readFileSync(filePath, "utf-8");
17
+ }
18
+ export async function captureCommand(name, options) {
19
+ const gitwhyDir = join(process.cwd(), ".gitwhy");
20
+ const change = resolveChange(gitwhyDir, name);
21
+ // Read planning artifacts
22
+ const intentContent = readFileOrEmpty(join(change.path, "intent.md"));
23
+ const designContent = readFileOrEmpty(join(change.path, "design.md"));
24
+ // Extract Decision Bridge data from design.md
25
+ const decisions = extractDecisions(designContent);
26
+ // Also extract decisions from intent.md if it has a Decisions to Make section
27
+ const intentDecisions = extractDecisions(intentContent);
28
+ const allDecisions = [...new Set([...decisions, ...intentDecisions])];
29
+ // Auto-detect commits and files changed since the change folder was created
30
+ let commits = [];
31
+ let filesChanged = [];
32
+ try {
33
+ const createdAt = getChangeFolderCreatedAt(change.path);
34
+ commits = getCommitsSince(createdAt);
35
+ filesChanged = getFilesChanged(createdAt);
36
+ }
37
+ catch {
38
+ // Gracefully handle if git operations fail
39
+ }
40
+ if (options.json) {
41
+ const output = {
42
+ template: renderContextXml(),
43
+ commits,
44
+ files_changed: filesChanged,
45
+ decisions_to_make: allDecisions,
46
+ change_name: change.name,
47
+ change_path: `.gitwhy/changes/${change.name}`,
48
+ };
49
+ console.log(JSON.stringify(output, null, 2));
50
+ return;
51
+ }
52
+ // Non-JSON mode: write ctx_<id>.md with GitWhy-compatible metadata header
53
+ const contextId = generateContextId();
54
+ const branch = getCurrentBranch();
55
+ const repository = getRemoteUrl();
56
+ const commitList = commits.length > 0 ? commits.map((c) => c.slice(0, 7)).join(", ") : "none";
57
+ const metadataHeader = [
58
+ `# ${change.name}`,
59
+ "",
60
+ `**Context ID:** ${contextId}`,
61
+ `**Agent:** whyspec`,
62
+ ...(repository ? [`**Repository:** ${repository}`] : []),
63
+ `**Branch:** ${branch}`,
64
+ `**Date:** ${new Date().toISOString()}`,
65
+ `**Change:** ${change.name}`,
66
+ `**Intent:** .gitwhy/changes/${change.name}/intent.md`,
67
+ `**Commits:** ${commitList}`,
68
+ "",
69
+ "---",
70
+ "",
71
+ ].join("\n");
72
+ const content = metadataHeader + renderContextXml() + "\n";
73
+ const fileName = `${contextId}.md`;
74
+ const filePath = join(change.path, fileName);
75
+ writeFileSync(filePath, content);
76
+ console.log(chalk.green("Captured context:") + ` ${fileName}`);
77
+ console.log(` ${chalk.dim("change:")} ${change.name}`);
78
+ console.log(` ${chalk.dim("branch:")} ${branch}`);
79
+ console.log(` ${chalk.dim("commits:")} ${commitList}`);
80
+ if (allDecisions.length > 0) {
81
+ console.log(` ${chalk.dim("decisions to map:")} ${allDecisions.length}`);
82
+ allDecisions.forEach((d) => console.log(` - ${d}`));
83
+ }
84
+ }
85
+ //# sourceMappingURL=capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/commands/capture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * whyspec debug — Create a structured debug session (scientific method).
3
+ *
4
+ * --json mode: returns path, template, and related past contexts.
5
+ * Non-JSON mode: creates debug.md, prints related contexts and next steps.
6
+ */
7
+ import { type SearchResult } from "../core/search.js";
8
+ export interface DebugJsonOutput {
9
+ path: string;
10
+ template: string;
11
+ related_contexts: SearchResult[];
12
+ }
13
+ export declare function debugCommand(name: string | undefined, options: {
14
+ json?: boolean;
15
+ }): Promise<void>;
16
+ //# sourceMappingURL=debug.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../src/commands/debug.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAErE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,YAAY,EAAE,CAAC;CAClC;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CAoEf"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * whyspec debug — Create a structured debug session (scientific method).
3
+ *
4
+ * --json mode: returns path, template, and related past contexts.
5
+ * Non-JSON mode: creates debug.md, prints related contexts and next steps.
6
+ */
7
+ import { mkdirSync, writeFileSync } from "node:fs";
8
+ import { join } from "node:path";
9
+ import chalk from "chalk";
10
+ import { slugify } from "../utils/slugify.js";
11
+ import { debugTemplate } from "../core/templates.js";
12
+ import { searchChanges } from "../core/search.js";
13
+ export async function debugCommand(name, options) {
14
+ if (!name) {
15
+ throw new Error("Bug description is required. Usage: whyspec debug \"description of the bug\"");
16
+ }
17
+ const repoRoot = process.cwd();
18
+ const slug = slugify(name);
19
+ const gitwhyDir = join(repoRoot, ".gitwhy");
20
+ const changePath = join(gitwhyDir, "changes", slug);
21
+ // Quick search for related contexts using first few words of the bug name.
22
+ const searchQuery = name.split(/\s+/).slice(0, 3).join(" ");
23
+ let relatedContexts = [];
24
+ try {
25
+ relatedContexts = searchChanges(repoRoot, searchQuery, { limit: 5 });
26
+ }
27
+ catch {
28
+ // Gracefully continue if search fails (e.g., no .gitwhy/ dir yet).
29
+ }
30
+ // Generate debug template.
31
+ const template = debugTemplate(name);
32
+ // Append related contexts section if any were found.
33
+ let fullTemplate = template;
34
+ if (relatedContexts.length > 0) {
35
+ fullTemplate += "\n## Related Contexts\n";
36
+ fullTemplate += "<!-- Past decisions and reasoning in this area -->\n";
37
+ for (const ctx of relatedContexts) {
38
+ fullTemplate += `- **${ctx.change_name}/${ctx.id}** (score: ${ctx.score}) — ${ctx.title}\n`;
39
+ fullTemplate += ` ${ctx.snippet}\n`;
40
+ }
41
+ }
42
+ if (options.json) {
43
+ const output = {
44
+ path: `.gitwhy/changes/${slug}`,
45
+ template: fullTemplate,
46
+ related_contexts: relatedContexts,
47
+ };
48
+ console.log(JSON.stringify(output, null, 2));
49
+ return;
50
+ }
51
+ // Non-JSON mode: create directory and file.
52
+ mkdirSync(changePath, { recursive: true });
53
+ writeFileSync(join(changePath, ".started"), new Date().toISOString());
54
+ writeFileSync(join(changePath, "debug.md"), fullTemplate);
55
+ console.log(chalk.green("Created debug session:") + ` ${slug}`);
56
+ console.log(` ${chalk.dim("path:")} .gitwhy/changes/${slug}/`);
57
+ console.log(` ${chalk.dim("file:")} debug.md`);
58
+ if (relatedContexts.length > 0) {
59
+ console.log();
60
+ console.log(chalk.bold("Related past contexts:"));
61
+ for (const ctx of relatedContexts) {
62
+ const scoreColor = ctx.score >= 100 ? chalk.green : ctx.score >= 30 ? chalk.yellow : chalk.dim;
63
+ console.log(` ${scoreColor(`[${ctx.score}]`)} ${ctx.change_name}/${ctx.id} — ${ctx.title}`);
64
+ }
65
+ }
66
+ console.log();
67
+ console.log(chalk.bold("Next steps:"));
68
+ console.log(` 1. Fill in ${chalk.cyan("Symptoms")} (expected vs actual)`);
69
+ console.log(` 2. Form 3+ ${chalk.cyan("Hypotheses")} with disproof criteria`);
70
+ console.log(` 3. ${chalk.cyan("Investigate")} each hypothesis with evidence`);
71
+ console.log(` 4. Verify ${chalk.cyan("Root Cause")} before fixing`);
72
+ console.log(` 5. Run ${chalk.cyan("whyspec capture")} to save debug reasoning`);
73
+ }
74
+ //# sourceMappingURL=debug.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug.js","sourceRoot":"","sources":["../../src/commands/debug.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * whyspec execute — Get execution context and track progress for a change.
3
+ *
4
+ * --json mode: returns plan file contents + task progress for agent consumption.
5
+ * Non-JSON mode: displays progress summary with task list.
6
+ */
7
+ export interface PendingTask {
8
+ line: number;
9
+ description: string;
10
+ }
11
+ export interface TaskProgress {
12
+ total: number;
13
+ completed: number;
14
+ remaining: number;
15
+ }
16
+ export interface ExecuteJsonOutput {
17
+ change_name: string;
18
+ intent_content: string;
19
+ design_content: string;
20
+ tasks_content: string;
21
+ progress: TaskProgress;
22
+ pending_tasks: PendingTask[];
23
+ }
24
+ /**
25
+ * Parse tasks.md for checkbox items, scoped to the ## Tasks section only.
26
+ * Ignores checkboxes in ## Verification and other sections.
27
+ * Recognizes: - [x], - [X] (completed) and - [ ] (pending).
28
+ */
29
+ export declare function parseTasks(content: string): {
30
+ progress: TaskProgress;
31
+ pending: PendingTask[];
32
+ };
33
+ export declare function executeCommand(name: string | undefined, options: {
34
+ json?: boolean;
35
+ }): Promise<void>;
36
+ //# sourceMappingURL=execute.d.ts.map