solvdex 1.0.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 (113) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +274 -0
  3. package/dist/hooks/error-lookup.d.ts +4 -0
  4. package/dist/hooks/error-lookup.d.ts.map +1 -0
  5. package/dist/hooks/error-lookup.js +92 -0
  6. package/dist/hooks/error-lookup.js.map +1 -0
  7. package/dist/hooks/post-task.d.ts +15 -0
  8. package/dist/hooks/post-task.d.ts.map +1 -0
  9. package/dist/hooks/post-task.js +246 -0
  10. package/dist/hooks/post-task.js.map +1 -0
  11. package/dist/hooks/prompt-enrich.d.ts +16 -0
  12. package/dist/hooks/prompt-enrich.d.ts.map +1 -0
  13. package/dist/hooks/prompt-enrich.js +141 -0
  14. package/dist/hooks/prompt-enrich.js.map +1 -0
  15. package/dist/hooks/session-start-cli.d.ts +3 -0
  16. package/dist/hooks/session-start-cli.d.ts.map +1 -0
  17. package/dist/hooks/session-start-cli.js +81 -0
  18. package/dist/hooks/session-start-cli.js.map +1 -0
  19. package/dist/hooks/session-start.d.ts +4 -0
  20. package/dist/hooks/session-start.d.ts.map +1 -0
  21. package/dist/hooks/session-start.js +134 -0
  22. package/dist/hooks/session-start.js.map +1 -0
  23. package/dist/src/audit.d.ts +63 -0
  24. package/dist/src/audit.d.ts.map +1 -0
  25. package/dist/src/audit.js +229 -0
  26. package/dist/src/audit.js.map +1 -0
  27. package/dist/src/cache.d.ts +54 -0
  28. package/dist/src/cache.d.ts.map +1 -0
  29. package/dist/src/cache.js +167 -0
  30. package/dist/src/cache.js.map +1 -0
  31. package/dist/src/config.d.ts +52 -0
  32. package/dist/src/config.d.ts.map +1 -0
  33. package/dist/src/config.js +175 -0
  34. package/dist/src/config.js.map +1 -0
  35. package/dist/src/entry.d.ts +154 -0
  36. package/dist/src/entry.d.ts.map +1 -0
  37. package/dist/src/entry.js +469 -0
  38. package/dist/src/entry.js.map +1 -0
  39. package/dist/src/errors.d.ts +65 -0
  40. package/dist/src/errors.d.ts.map +1 -0
  41. package/dist/src/errors.js +121 -0
  42. package/dist/src/errors.js.map +1 -0
  43. package/dist/src/frontmatter.d.ts +28 -0
  44. package/dist/src/frontmatter.d.ts.map +1 -0
  45. package/dist/src/frontmatter.js +111 -0
  46. package/dist/src/frontmatter.js.map +1 -0
  47. package/dist/src/index.d.ts +35 -0
  48. package/dist/src/index.d.ts.map +1 -0
  49. package/dist/src/index.js +188 -0
  50. package/dist/src/index.js.map +1 -0
  51. package/dist/src/maturity.d.ts +31 -0
  52. package/dist/src/maturity.d.ts.map +1 -0
  53. package/dist/src/maturity.js +96 -0
  54. package/dist/src/maturity.js.map +1 -0
  55. package/dist/src/quality.d.ts +23 -0
  56. package/dist/src/quality.d.ts.map +1 -0
  57. package/dist/src/quality.js +236 -0
  58. package/dist/src/quality.js.map +1 -0
  59. package/dist/src/search.d.ts +35 -0
  60. package/dist/src/search.d.ts.map +1 -0
  61. package/dist/src/search.js +263 -0
  62. package/dist/src/search.js.map +1 -0
  63. package/dist/src/similarity.d.ts +42 -0
  64. package/dist/src/similarity.d.ts.map +1 -0
  65. package/dist/src/similarity.js +111 -0
  66. package/dist/src/similarity.js.map +1 -0
  67. package/dist/src/stats.d.ts +56 -0
  68. package/dist/src/stats.d.ts.map +1 -0
  69. package/dist/src/stats.js +198 -0
  70. package/dist/src/stats.js.map +1 -0
  71. package/dist/src/templates.d.ts +63 -0
  72. package/dist/src/templates.d.ts.map +1 -0
  73. package/dist/src/templates.js +347 -0
  74. package/dist/src/templates.js.map +1 -0
  75. package/dist/src/transfer.d.ts +92 -0
  76. package/dist/src/transfer.d.ts.map +1 -0
  77. package/dist/src/transfer.js +215 -0
  78. package/dist/src/transfer.js.map +1 -0
  79. package/dist/src/types.d.ts +270 -0
  80. package/dist/src/types.d.ts.map +1 -0
  81. package/dist/src/types.js +153 -0
  82. package/dist/src/types.js.map +1 -0
  83. package/dist/src/validate.d.ts +90 -0
  84. package/dist/src/validate.d.ts.map +1 -0
  85. package/dist/src/validate.js +295 -0
  86. package/dist/src/validate.js.map +1 -0
  87. package/hooks/error-lookup.ts +110 -0
  88. package/hooks/hooks.json +49 -0
  89. package/hooks/post-task.ts +309 -0
  90. package/hooks/prompt-enrich.ts +162 -0
  91. package/hooks/session-start-cli.ts +96 -0
  92. package/hooks/session-start.ts +159 -0
  93. package/package.json +40 -0
  94. package/scripts/error-lookup.py +64 -0
  95. package/scripts/post-task.py +60 -0
  96. package/scripts/prompt-enrich.py +64 -0
  97. package/scripts/session-start.py +64 -0
  98. package/skills/wiki/SKILL.md +61 -0
  99. package/skills/wiki-add/SKILL.md +90 -0
  100. package/skills/wiki-browse/SKILL.md +108 -0
  101. package/skills/wiki-capture/SKILL.md +265 -0
  102. package/skills/wiki-explorer/SKILL.md +223 -0
  103. package/skills/wiki-export/SKILL.md +101 -0
  104. package/skills/wiki-fix/SKILL.md +86 -0
  105. package/skills/wiki-flag/SKILL.md +47 -0
  106. package/skills/wiki-import/SKILL.md +128 -0
  107. package/skills/wiki-init/SKILL.md +72 -0
  108. package/skills/wiki-scan/SKILL.md +98 -0
  109. package/skills/wiki-search/SKILL.md +86 -0
  110. package/skills/wiki-stats/SKILL.md +129 -0
  111. package/skills/wiki-status/SKILL.md +78 -0
  112. package/skills/wiki-test-trigger/SKILL.md +173 -0
  113. package/skills/wiki-validate/SKILL.md +62 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 duc.do
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,274 @@
1
+ # Solvdex
2
+
3
+ [![Tests](https://img.shields.io/badge/tests-204%20passed-brightgreen)](./tests)
4
+ [![Version](https://img.shields.io/badge/version-0.3.0-blue)](./package.json)
5
+ [![License](https://img.shields.io/badge/license-MIT-green)](./LICENSE)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0-blue)](https://www.typescriptlang.org/)
7
+
8
+ > **An index of solved problems.** A Claude Code plugin that auto-captures and retrieves project knowledge.
9
+
10
+ ```
11
+ ┌─────────────────────────────────────────────────────────────┐
12
+ │ Error: ETIMEDOUT connecting to database │
13
+ ├─────────────────────────────────────────────────────────────┤
14
+ │ 📚 Solvdex found a solution: │
15
+ │ "Database Connection Timeout" │
16
+ │ Confidence: 85 │
17
+ │ │
18
+ │ Solution: Increase pool timeout in config... │
19
+ └─────────────────────────────────────────────────────────────┘
20
+ ```
21
+
22
+ ## Features
23
+
24
+ | Feature | Description |
25
+ |---------|-------------|
26
+ | 🔄 **Auto-Capture** | Saves solutions when errors are resolved |
27
+ | 🔍 **Auto-Lookup** | Surfaces relevant knowledge on errors |
28
+ | 📊 **7 Categories** | Organized knowledge across development domains |
29
+ | 🎯 **Trigger Patterns** | Regex matching for automatic error detection |
30
+ | 📈 **Confidence Tracking** | Trust scores with decay over time |
31
+ | 🔗 **Cross-References** | Link related entries and source files |
32
+
33
+ ## Categories
34
+
35
+ ```
36
+ .wiki/
37
+ ├── issues/ # Bug fixes, error solutions
38
+ ├── patterns/ # Reusable code patterns
39
+ ├── gotchas/ # Pitfalls to avoid
40
+ ├── testing/ # Test strategies, mocks
41
+ ├── docs/ # Documentation guides
42
+ ├── security/ # Auth, vulnerabilities
43
+ └── performance/ # Optimizations, benchmarks
44
+ ```
45
+
46
+ ## Quick Start
47
+
48
+ ```bash
49
+ # Initialize wiki
50
+ /wiki init
51
+
52
+ # Search for solutions
53
+ /wiki search "database timeout"
54
+
55
+ # Add current solution
56
+ /wiki add --category=issues
57
+
58
+ # Browse entries
59
+ /wiki browse
60
+ ```
61
+
62
+ ## Commands
63
+
64
+ ### Core Commands
65
+
66
+ | Command | Description |
67
+ |---------|-------------|
68
+ | `/wiki init` | Create `.wiki/` structure |
69
+ | `/wiki add` | Save current solution |
70
+ | `/wiki search <query>` | Full-text search |
71
+ | `/wiki browse` | List entries with filters |
72
+
73
+ ### Management Commands
74
+
75
+ | Command | Description |
76
+ |---------|-------------|
77
+ | `/wiki status` | Quick health overview |
78
+ | `/wiki stats` | Detailed analytics |
79
+ | `/wiki validate` | Check for issues |
80
+ | `/wiki scan` | Generate stubs from project |
81
+ | `/wiki flag <entry>` | Mark for review |
82
+ | `/wiki fix <entry>` | Update flagged entry |
83
+
84
+ ### Transfer Commands
85
+
86
+ | Command | Description |
87
+ |---------|-------------|
88
+ | `/wiki export [file]` | Export to JSON |
89
+ | `/wiki import <file>` | Import from JSON |
90
+ | `/wiki test-trigger` | Test regex patterns |
91
+
92
+ ### Agents
93
+
94
+ | Command | Description |
95
+ |---------|-------------|
96
+ | `/wiki explore <query>` | Deep multi-strategy search |
97
+ | `/wiki capture` | Extract knowledge from conversation |
98
+
99
+ ## How It Works
100
+
101
+ ### Automatic Knowledge Capture
102
+
103
+ ```
104
+ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
105
+ │ You solve │────▶│ Solvdex │────▶│ .wiki/ │
106
+ │ an error │ │ detects │ │ saved! │
107
+ └──────────────┘ └──────────────┘ └──────────────┘
108
+
109
+ Signals detected:
110
+ • error_resolved → issues/
111
+ • workaround → gotchas/
112
+ • user confirms → auto-detect category
113
+ • explicit save → "remember this"
114
+ ```
115
+
116
+ ### Automatic Knowledge Retrieval
117
+
118
+ ```
119
+ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
120
+ │ Error │────▶│ Solvdex │────▶│ Solution │
121
+ │ occurs │ │ matches │ │ displayed │
122
+ └──────────────┘ └──────────────┘ └──────────────┘
123
+
124
+ Lookup triggers:
125
+ • Session start → relevant context
126
+ • Error match → trigger patterns
127
+ • Prompt keywords → category detection
128
+ ```
129
+
130
+ ## Entry Format
131
+
132
+ ```yaml
133
+ ---
134
+ title: Database Connection Timeout
135
+ created: 2025-01-20
136
+ status: active
137
+ confidence: 85
138
+ tags: [database, timeout, postgres]
139
+ trigger: "ETIMEDOUT.*postgres"
140
+ ---
141
+
142
+ ## Problem
143
+ Connection times out after 30 seconds...
144
+
145
+ ## Solution
146
+ Increase timeout and add connection pool...
147
+
148
+ ## Related
149
+ - [[issues/connection-pool]]
150
+ - `src/db/config.ts:45`
151
+ ```
152
+
153
+ > **Note:** Entries also include maturity tracking fields (`maturity`, `use_count`, `last_used`). See [Entry Maturity System](#entry-maturity-system) below.
154
+
155
+ ### Entry Maturity System
156
+
157
+ Solvdex automatically tracks and promotes entries through maturity phases based on usage:
158
+
159
+ | Maturity | Criteria | Confidence | Meaning |
160
+ |----------|----------|------------|---------|
161
+ | **captured** | 0-2 uses | 40 | Newly documented, unverified |
162
+ | **verified** | 3+ uses | 70 | Proven to work multiple times |
163
+ | **validated** | 10+ uses, 30+ days old | 90 | Battle-tested over time |
164
+
165
+ **Automatic Promotion:**
166
+ - Entries start as `captured` when created
167
+ - Maturity is evaluated automatically each time `recordEntryUsage()` is called
168
+ - After 3 successful uses → promoted to `verified`
169
+ - After 10 uses AND 30+ days → promoted to `validated`
170
+ - Confidence scores update automatically with maturity
171
+
172
+ **Safety Features:**
173
+ - Flagged entries freeze maturity progression
174
+ - Manual maturity overrides are respected
175
+ - Maturity only goes up (no demotion)
176
+ - All promotions logged in audit trail
177
+
178
+ **Example Entry:**
179
+ ```yaml
180
+ ---
181
+ title: Fix Redis Connection Timeout
182
+ maturity: verified
183
+ confidence: 70
184
+ use_count: 5
185
+ last_used: 2025-01-23
186
+ audit:
187
+ - date: 2025-01-20
188
+ action: created
189
+ by: user
190
+ - date: 2025-01-22
191
+ action: maturity_promoted
192
+ by: system
193
+ context: "Auto-promoted: captured → verified (3 uses)"
194
+ ---
195
+ ```
196
+
197
+ ## Confidence Scale
198
+
199
+ | Score | Level | Meaning |
200
+ |-------|-------|---------|
201
+ | 90-100 | 🟢 High | Typically validated entries |
202
+ | 60-89 | 🟡 Medium | Typically verified entries or manually set |
203
+ | 0-59 | 🔴 Low | Typically captured entries or stubs |
204
+
205
+ Confidence auto-decays for entries unused for 90+ days.
206
+
207
+ ## Hooks
208
+
209
+ Real-time integration with Claude Code:
210
+
211
+ | Hook | When | Action |
212
+ |------|------|--------|
213
+ | `SessionStart` | New conversation | Surface relevant entries |
214
+ | `UserPromptSubmit` | Each prompt | Enrich with context |
215
+ | `PostToolUseFailure` | Error occurs | Show matching solutions |
216
+ | `Stop` | Task completes | Offer to capture knowledge |
217
+
218
+ ## Installation
219
+
220
+ ### From Source
221
+
222
+ ```bash
223
+ git clone https://github.com/ducdmdev/solvdex.git
224
+ cd solvdex
225
+ npm install
226
+ npm run build
227
+ ```
228
+
229
+ ### Via Claude Code Marketplace
230
+
231
+ ```bash
232
+ # Coming soon
233
+ /plugin install solvdex
234
+ ```
235
+
236
+ ## Documentation
237
+
238
+ | Document | Description |
239
+ |----------|-------------|
240
+ | [Getting Started](./docs/getting-started.md) | Quick setup guide |
241
+ | [Architecture](./docs/architecture.md) | System design |
242
+ | [Workflows](./docs/workflows.md) | Hook and skill flows |
243
+ | [Use Cases](./docs/use-cases.md) | Common scenarios |
244
+
245
+ ## Development
246
+
247
+ ```bash
248
+ npm install # Install dependencies
249
+ npm run build # Compile TypeScript
250
+ npm test # Run 204 tests
251
+ npm run lint # Check code style
252
+ ```
253
+
254
+ ## Project Structure
255
+
256
+ ```
257
+ solvdex/
258
+ ├── src/ # Core TypeScript library
259
+ ├── skills/ # 16 Claude Code skills
260
+ ├── hooks/ # 4 automated hooks
261
+ ├── docs/ # Documentation
262
+ └── tests/ # Test suite (204 tests)
263
+ ```
264
+
265
+ ## License
266
+
267
+ MIT © [duc.do](https://github.com/ducdmdev)
268
+
269
+ ---
270
+
271
+ <p align="center">
272
+ <b>Stop re-solving the same problems.</b><br>
273
+ <i>Build your knowledge index with Solvdex.</i>
274
+ </p>
@@ -0,0 +1,4 @@
1
+ import { ErrorLookupOutput } from '../src/index.js';
2
+ export declare function onErrorLookup(input: unknown): Promise<ErrorLookupOutput | null>;
3
+ export default onErrorLookup;
4
+ //# sourceMappingURL=error-lookup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-lookup.d.ts","sourceRoot":"","sources":["../../hooks/error-lookup.ts"],"names":[],"mappings":"AACA,OAAO,EAML,iBAAiB,EAKlB,MAAM,iBAAiB,CAAC;AAezB,wBAAsB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAwErF;AAUD,eAAe,aAAa,CAAC"}
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.onErrorLookup = onErrorLookup;
4
+ // hooks/error-lookup.ts
5
+ const index_js_1 = require("../src/index.js");
6
+ /**
7
+ * Extracts the solution section from wiki entry content.
8
+ */
9
+ function extractSolution(content) {
10
+ // Look for Solution heading
11
+ const solutionMatch = content.match(/## Solution\n([\s\S]*?)(?=\n## |$)/);
12
+ if (solutionMatch) {
13
+ return solutionMatch[1].trim().slice(0, 200) + '...';
14
+ }
15
+ // Fallback: first 200 chars
16
+ return content.slice(0, 200) + '...';
17
+ }
18
+ async function onErrorLookup(input) {
19
+ try {
20
+ // Validate input first
21
+ const validatedInput = (0, index_js_1.validateErrorLookupInput)(input);
22
+ const { projectRoot, errorText, toolResult } = validatedInput;
23
+ // Get error text from either direct input or tool stderr
24
+ const error = errorText || toolResult?.stderr || '';
25
+ if (!error || !(0, index_js_1.wikiExists)(projectRoot)) {
26
+ return null;
27
+ }
28
+ // Try to match error against trigger patterns
29
+ const results = await (0, index_js_1.matchTrigger)(projectRoot, error);
30
+ const bestMatch = (0, index_js_1.getBestMatch)(results);
31
+ if (bestMatch && bestMatch.entry.frontmatter.confidence >= index_js_1.CONFIDENCE.THRESHOLD) {
32
+ // Record usage for analytics
33
+ try {
34
+ const { recordEntryUsage } = await import('../src/index.js');
35
+ recordEntryUsage(projectRoot, bestMatch.entry.path);
36
+ }
37
+ catch {
38
+ // Usage tracking failure is non-critical
39
+ }
40
+ // Output for Claude Code hook integration (user-facing console logs)
41
+ console.log(`📚 Solvdex found a solution:`);
42
+ console.log(` "${bestMatch.entry.frontmatter.title}"`);
43
+ console.log(` Confidence: ${bestMatch.entry.frontmatter.confidence}`);
44
+ console.log(` `);
45
+ console.log(` Solution: ${extractSolution(bestMatch.entry.content)}`);
46
+ // Structured output for Claude Code (includes both old and new format for backward compatibility)
47
+ const output = {
48
+ // Old format (for backward compatibility)
49
+ type: 'wiki_solution',
50
+ message: `Wiki: Found "${bestMatch.entry.frontmatter.title}" (confidence: ${bestMatch.entry.frontmatter.confidence})`,
51
+ entry: bestMatch.entry,
52
+ // New format (Claude Code integration)
53
+ continue: true,
54
+ hookSpecificOutput: {
55
+ type: 'solution_found',
56
+ message: `Found solution: "${bestMatch.entry.frontmatter.title}"`,
57
+ entries: [{
58
+ title: bestMatch.entry.frontmatter.title,
59
+ category: bestMatch.entry.category,
60
+ path: bestMatch.entry.path,
61
+ confidence: bestMatch.entry.frontmatter.confidence
62
+ }]
63
+ },
64
+ additionalContext: formatSolutionForContext(bestMatch)
65
+ };
66
+ // Output JSON marker + JSON (MUST be last output)
67
+ console.log('\n__HOOK_OUTPUT__');
68
+ console.log(JSON.stringify(output));
69
+ return output;
70
+ }
71
+ return null;
72
+ }
73
+ catch (error) {
74
+ // Handle validation errors separately
75
+ if (error instanceof index_js_1.ValidationError) {
76
+ console.error(`[Solvdex] Invalid input: ${error.message}`);
77
+ return null;
78
+ }
79
+ // Graceful degradation - log error but don't crash
80
+ console.error(`[Solvdex] Error in error-lookup hook: ${error instanceof Error ? error.message : 'Unknown error'}`);
81
+ return null;
82
+ }
83
+ }
84
+ /**
85
+ * Formats a solution match into a readable context string for Claude Code.
86
+ */
87
+ function formatSolutionForContext(match) {
88
+ const e = match.entry;
89
+ return `## ${e.frontmatter.title} (${e.category})\nConfidence: ${e.frontmatter.confidence}\n\n${e.content}`;
90
+ }
91
+ exports.default = onErrorLookup;
92
+ //# sourceMappingURL=error-lookup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-lookup.js","sourceRoot":"","sources":["../../hooks/error-lookup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { PostTaskOutput } from '../src/index.js';
2
+ interface TaskContext {
3
+ projectRoot: string;
4
+ taskDescription: string;
5
+ outcome: 'success' | 'failure';
6
+ errorEncountered?: string;
7
+ errorResolved?: boolean;
8
+ filesModified?: string[];
9
+ userConfirmation?: string;
10
+ codeChanges?: string;
11
+ actionHistory?: string[];
12
+ }
13
+ export declare function onPostTask(context: TaskContext): Promise<PostTaskOutput | null>;
14
+ export default onPostTask;
15
+ //# sourceMappingURL=post-task.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-task.d.ts","sourceRoot":"","sources":["../../hooks/post-task.ts"],"names":[],"mappings":"AACA,OAAO,EAML,cAAc,EACf,MAAM,iBAAiB,CAAC;AAEzB,UAAU,WAAW;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,SAAS,GAAG,SAAS,CAAC;IAC/B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAWD,wBAAsB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAmFrF;AAkMD,eAAe,UAAU,CAAC"}
@@ -0,0 +1,246 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.onPostTask = onPostTask;
4
+ // hooks/post-task.ts
5
+ const index_js_1 = require("../src/index.js");
6
+ // Default enabled signals (can be overridden by future config)
7
+ const DEFAULT_SIGNALS = [
8
+ 'error_resolved',
9
+ 'user_confirmation',
10
+ 'explicit_save',
11
+ 'repeated_pattern',
12
+ 'workaround_applied'
13
+ ];
14
+ async function onPostTask(context) {
15
+ try {
16
+ const { projectRoot } = context;
17
+ if (!(0, index_js_1.wikiExists)(projectRoot)) {
18
+ return null;
19
+ }
20
+ // Check signals
21
+ const signal = detectSignal(context, DEFAULT_SIGNALS);
22
+ if (!signal) {
23
+ return null;
24
+ }
25
+ // Extract entry details
26
+ const entryDetails = extractEntryDetails(context, signal);
27
+ // Check for duplicates before creating (but don't block on it)
28
+ let isDuplicate = false;
29
+ try {
30
+ const { checkDuplicate } = await import('../src/index.js');
31
+ const dupCheck = await checkDuplicate(projectRoot, entryDetails.title, entryDetails.tags, entryDetails.category);
32
+ isDuplicate = dupCheck.isDuplicate;
33
+ if (isDuplicate) {
34
+ console.log(`📚 Solvdex: Skipping duplicate "${entryDetails.title}"`);
35
+ console.log(` Similar to: "${dupCheck.matchedEntry?.frontmatter.title}"`);
36
+ return null;
37
+ }
38
+ }
39
+ catch {
40
+ // Duplicate check failure is non-critical, proceed with creation
41
+ }
42
+ // Create entry
43
+ const entry = (0, index_js_1.createEntry)(projectRoot, {
44
+ category: entryDetails.category,
45
+ title: entryDetails.title,
46
+ tags: entryDetails.tags,
47
+ content: entryDetails.content,
48
+ trigger: entryDetails.trigger,
49
+ autoCapture: true,
50
+ stub: true,
51
+ source: `auto-capture:${signal}`
52
+ });
53
+ // Output for Claude Code Stop hook integration (user-facing console logs)
54
+ console.log(`📚 Solvdex: Captured "${entry.frontmatter.title}"`);
55
+ console.log(` Category: ${entry.category}`);
56
+ console.log(` Signal: ${signal}`);
57
+ // Structured output for Claude Code (includes both old and new format for backward compatibility)
58
+ const output = {
59
+ // Old format (for backward compatibility)
60
+ type: 'wiki_captured',
61
+ message: `Wiki: Saved "${entry.frontmatter.title}" to ${entry.category}/`,
62
+ entry,
63
+ signal,
64
+ // New format (Claude Code integration)
65
+ continue: true,
66
+ hookSpecificOutput: {
67
+ type: 'entry_captured',
68
+ message: `Captured "${entry.frontmatter.title}" to ${entry.category}/`,
69
+ entryPath: entry.path
70
+ },
71
+ additionalContext: formatEntryForContext(entry, signal)
72
+ };
73
+ // Output JSON marker + JSON (MUST be last output)
74
+ console.log('\n__HOOK_OUTPUT__');
75
+ console.log(JSON.stringify(output));
76
+ return output;
77
+ }
78
+ catch (error) {
79
+ // Graceful degradation - log error but don't crash
80
+ console.error(`[Solvdex] Error in post-task hook: ${error instanceof Error ? error.message : 'Unknown error'}`);
81
+ return null;
82
+ }
83
+ }
84
+ /**
85
+ * Detects if similar actions have been performed 3+ times.
86
+ * Returns the repeated action if found.
87
+ */
88
+ function detectRepeatedPattern(actionHistory) {
89
+ if (!actionHistory || actionHistory.length < 3) {
90
+ return null;
91
+ }
92
+ // Count occurrences of each action
93
+ const counts = {};
94
+ for (const action of actionHistory) {
95
+ const normalized = action.toLowerCase().trim();
96
+ counts[normalized] = (counts[normalized] || 0) + 1;
97
+ }
98
+ // Find action repeated 3+ times
99
+ for (const [action, count] of Object.entries(counts)) {
100
+ if (count >= 3) {
101
+ return action;
102
+ }
103
+ }
104
+ return null;
105
+ }
106
+ function detectSignal(context, enabledSignals) {
107
+ // Signal 1: Error resolved
108
+ if (enabledSignals.includes('error_resolved') &&
109
+ context.errorEncountered &&
110
+ context.errorResolved &&
111
+ context.outcome === 'success') {
112
+ return 'error_resolved';
113
+ }
114
+ // Signal 2: User confirmation
115
+ if (enabledSignals.includes('user_confirmation') &&
116
+ context.userConfirmation &&
117
+ isPositiveConfirmation(context.userConfirmation)) {
118
+ return 'user_confirmation';
119
+ }
120
+ // Signal 3: Explicit save request
121
+ if (enabledSignals.includes('explicit_save') &&
122
+ context.userConfirmation &&
123
+ isExplicitSaveRequest(context.userConfirmation)) {
124
+ return 'explicit_save';
125
+ }
126
+ // Signal 4: Repeated pattern
127
+ if (enabledSignals.includes('repeated_pattern') && context.actionHistory) {
128
+ const repeatedAction = detectRepeatedPattern(context.actionHistory);
129
+ if (repeatedAction) {
130
+ return 'repeated_pattern';
131
+ }
132
+ }
133
+ // Signal 5: Workaround applied (detect HACK/WORKAROUND comments)
134
+ if (enabledSignals.includes('workaround_applied') &&
135
+ context.codeChanges &&
136
+ hasWorkaroundMarkers(context.codeChanges)) {
137
+ return 'workaround_applied';
138
+ }
139
+ return null;
140
+ }
141
+ function isPositiveConfirmation(text) {
142
+ const positivePatterns = [
143
+ 'that fixed it',
144
+ 'works now',
145
+ 'perfect',
146
+ 'that worked',
147
+ 'thank you',
148
+ 'great',
149
+ 'awesome',
150
+ 'solved'
151
+ ];
152
+ const textLower = text.toLowerCase();
153
+ return positivePatterns.some(p => textLower.includes(p));
154
+ }
155
+ function isExplicitSaveRequest(text) {
156
+ const savePatterns = [
157
+ 'save this to wiki',
158
+ 'remember this',
159
+ 'add to wiki',
160
+ 'wiki this',
161
+ 'document this'
162
+ ];
163
+ const textLower = text.toLowerCase();
164
+ return savePatterns.some(p => textLower.includes(p));
165
+ }
166
+ function hasWorkaroundMarkers(codeChanges) {
167
+ const workaroundPatterns = [
168
+ /\/\/\s*(HACK|WORKAROUND|TODO|FIXME):/i,
169
+ /\/\*\s*(HACK|WORKAROUND|TODO|FIXME):/i,
170
+ /#\s*(HACK|WORKAROUND|TODO|FIXME):/i
171
+ ];
172
+ return workaroundPatterns.some(pattern => pattern.test(codeChanges));
173
+ }
174
+ function extractEntryDetails(context, signal) {
175
+ // Determine category based on signal and task keywords (7 categories)
176
+ let category = 'issues'; // default
177
+ if (signal === 'error_resolved') {
178
+ category = 'issues';
179
+ }
180
+ else if (signal === 'workaround_applied') {
181
+ category = 'gotchas';
182
+ }
183
+ else if (signal === 'repeated_pattern') {
184
+ category = 'patterns';
185
+ }
186
+ else if (context.taskDescription) {
187
+ const task = context.taskDescription.toLowerCase();
188
+ // Testing signals
189
+ if (task.includes('test') || task.includes('mock') || task.includes('fixture')) {
190
+ category = 'testing';
191
+ }
192
+ // Documentation signals
193
+ else if (task.includes('document') || task.includes('readme') || task.includes('guide')) {
194
+ category = 'docs';
195
+ }
196
+ // Security signals
197
+ else if (task.includes('auth') || task.includes('security') || task.includes('permission')) {
198
+ category = 'security';
199
+ }
200
+ // Performance signals
201
+ else if (task.includes('slow') || task.includes('optimize') || task.includes('performance')) {
202
+ category = 'performance';
203
+ }
204
+ // Pattern signals
205
+ else if (task.includes('pattern') || task.includes('reusable')) {
206
+ category = 'patterns';
207
+ }
208
+ // Gotcha signals
209
+ else if (task.includes('careful') || task.includes('avoid') || task.includes('pitfall')) {
210
+ category = 'gotchas';
211
+ }
212
+ }
213
+ // Generate title from task or error
214
+ const title = context.errorEncountered
215
+ ? `Fix: ${context.errorEncountered.substring(0, 50)}`
216
+ : context.taskDescription?.substring(0, 50) || 'Auto-captured entry';
217
+ // Extract tags from context
218
+ const tags = [];
219
+ if (context.filesModified) {
220
+ // Add file extension tags
221
+ const extensions = new Set(context.filesModified
222
+ .map(f => f.split('.').pop())
223
+ .filter(Boolean));
224
+ tags.push(...Array.from(extensions));
225
+ }
226
+ if (signal) {
227
+ tags.push(`auto:${signal}`);
228
+ }
229
+ // Generate stub content
230
+ const stubContent = (0, index_js_1.generateStubContent)(category);
231
+ return {
232
+ category,
233
+ title: title.replace(/[^\w\s-]/g, '').trim(),
234
+ tags,
235
+ content: stubContent,
236
+ trigger: context.errorEncountered
237
+ };
238
+ }
239
+ /**
240
+ * Formats a captured entry into a readable context string for Claude Code.
241
+ */
242
+ function formatEntryForContext(entry, signal) {
243
+ return `## Captured Entry: ${entry.frontmatter.title}\nCategory: ${entry.category}\nSignal: ${signal}\nPath: ${entry.path}\n\n${entry.content.substring(0, 300)}...`;
244
+ }
245
+ exports.default = onPostTask;
246
+ //# sourceMappingURL=post-task.js.map