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
@@ -0,0 +1,295 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.validateEntry = validateEntry;
37
+ exports.validateWiki = validateWiki;
38
+ exports.flagEntry = flagEntry;
39
+ exports.deprecateEntry = deprecateEntry;
40
+ exports.adjustConfidence = adjustConfidence;
41
+ exports.markSolutionWorked = markSolutionWorked;
42
+ exports.markSolutionFailed = markSolutionFailed;
43
+ // src/validate.ts
44
+ const fs = __importStar(require("fs"));
45
+ const path = __importStar(require("path"));
46
+ const types_js_1 = require("./types.js");
47
+ const entry_js_1 = require("./entry.js");
48
+ /**
49
+ * Extracts file references from content (backtick paths like `src/file.ts`).
50
+ *
51
+ * @param content - The markdown content to search
52
+ * @returns Array of file paths found in backticks
53
+ */
54
+ function extractFileReferences(content) {
55
+ // Match backtick-enclosed paths that look like file paths
56
+ // Pattern: `path/to/file.ext` or `./path/to/file.ext` or `../path/to/file.ext`
57
+ const regex = /`((?:\.{0,2}\/)?[\w./-]+\.\w+)`/g;
58
+ const matches = [];
59
+ let match;
60
+ while ((match = regex.exec(content)) !== null) {
61
+ const filePath = match[1];
62
+ // Filter out obvious non-file-paths (URLs, etc.)
63
+ if (!filePath.includes('://') && !filePath.startsWith('http')) {
64
+ matches.push(filePath);
65
+ }
66
+ }
67
+ return matches;
68
+ }
69
+ /**
70
+ * Extracts C3 references from content ([[c3-component]]).
71
+ *
72
+ * @param content - The markdown content to search
73
+ * @returns Array of C3 references found
74
+ */
75
+ function extractC3References(content) {
76
+ // Match [[c3-xxx]] pattern
77
+ const regex = /\[\[(c3-[\w-]+)\]\]/g;
78
+ const matches = [];
79
+ let match;
80
+ while ((match = regex.exec(content)) !== null) {
81
+ matches.push(match[1]);
82
+ }
83
+ return matches;
84
+ }
85
+ /**
86
+ * Checks if a file exists relative to the project root.
87
+ *
88
+ * @param projectRoot - The root directory of the project
89
+ * @param filePath - The file path to check
90
+ * @returns True if the file exists
91
+ */
92
+ function fileExists(projectRoot, filePath) {
93
+ const fullPath = path.join(projectRoot, filePath);
94
+ return fs.existsSync(fullPath);
95
+ }
96
+ /**
97
+ * Validates a single wiki entry for issues.
98
+ *
99
+ * @param projectRoot - The root directory of the project
100
+ * @param entryPath - Relative path to the entry from the wiki directory
101
+ * @returns Array of validation issues found
102
+ */
103
+ function validateEntry(projectRoot, entryPath) {
104
+ const entry = (0, entry_js_1.readEntry)(projectRoot, entryPath);
105
+ if (!entry) {
106
+ return [{
107
+ type: 'broken_reference',
108
+ message: `Entry not found: ${entryPath}`,
109
+ entryPath
110
+ }];
111
+ }
112
+ const issues = [];
113
+ // Check for broken file references
114
+ const fileRefs = extractFileReferences(entry.content);
115
+ for (const fileRef of fileRefs) {
116
+ if (!fileExists(projectRoot, fileRef)) {
117
+ issues.push({
118
+ type: 'broken_reference',
119
+ message: `Broken file reference: ${fileRef}`,
120
+ entryPath
121
+ });
122
+ }
123
+ }
124
+ // Check for missing C3 references (C3 refs that don't resolve)
125
+ // For now, we just check if the C3 reference format is used but can't be validated
126
+ // This is a placeholder for when C3 integration is implemented
127
+ const c3Refs = extractC3References(entry.content);
128
+ const c3Path = path.join(projectRoot, '.c3');
129
+ if (c3Refs.length > 0 && !fs.existsSync(c3Path)) {
130
+ for (const c3Ref of c3Refs) {
131
+ issues.push({
132
+ type: 'missing_c3',
133
+ message: `C3 reference cannot be validated (no .c3 directory): ${c3Ref}`,
134
+ entryPath
135
+ });
136
+ }
137
+ }
138
+ // Check if entry is flagged
139
+ if (entry.frontmatter.status === 'flagged') {
140
+ issues.push({
141
+ type: 'flagged',
142
+ message: `Entry is flagged for review`,
143
+ entryPath
144
+ });
145
+ }
146
+ // Check if entry is a stub
147
+ if (entry.frontmatter.stub) {
148
+ issues.push({
149
+ type: 'stub',
150
+ message: `Entry is a stub and needs expansion`,
151
+ entryPath
152
+ });
153
+ }
154
+ return issues;
155
+ }
156
+ /**
157
+ * Validates the entire wiki and returns a comprehensive report.
158
+ *
159
+ * @param projectRoot - The root directory of the project
160
+ * @returns Validation report with counts and issues
161
+ */
162
+ async function validateWiki(projectRoot) {
163
+ const entries = await (0, entry_js_1.listEntries)(projectRoot);
164
+ const report = {
165
+ total: entries.length,
166
+ active: 0,
167
+ flagged: 0,
168
+ deprecated: 0,
169
+ issues: []
170
+ };
171
+ for (const entry of entries) {
172
+ // Count by status
173
+ switch (entry.frontmatter.status) {
174
+ case 'active':
175
+ report.active++;
176
+ break;
177
+ case 'flagged':
178
+ report.flagged++;
179
+ break;
180
+ case 'deprecated':
181
+ report.deprecated++;
182
+ break;
183
+ }
184
+ // Validate each entry and collect issues
185
+ const entryIssues = validateEntry(projectRoot, entry.path);
186
+ report.issues.push(...entryIssues);
187
+ }
188
+ return report;
189
+ }
190
+ /**
191
+ * Marks an entry as flagged with the given reason.
192
+ *
193
+ * @param projectRoot - The root directory of the project
194
+ * @param entryPath - Relative path to the entry from the wiki directory
195
+ * @param reason - The reason for flagging the entry
196
+ * @returns The updated WikiEntry
197
+ */
198
+ function flagEntry(projectRoot, entryPath, reason) {
199
+ return (0, entry_js_1.updateEntry)(projectRoot, entryPath, { status: 'flagged' }, {
200
+ by: 'claude',
201
+ reason,
202
+ context: 'validation'
203
+ });
204
+ }
205
+ /**
206
+ * Marks an entry as deprecated with the given reason.
207
+ *
208
+ * @param projectRoot - The root directory of the project
209
+ * @param entryPath - Relative path to the entry from the wiki directory
210
+ * @param reason - The reason for deprecating the entry
211
+ * @returns The updated WikiEntry
212
+ */
213
+ function deprecateEntry(projectRoot, entryPath, reason) {
214
+ return (0, entry_js_1.updateEntry)(projectRoot, entryPath, { status: 'deprecated' }, {
215
+ by: 'claude',
216
+ reason,
217
+ context: 'validation'
218
+ });
219
+ }
220
+ /**
221
+ * Adjusts the confidence level of an entry up or down.
222
+ * Up: +20 points (capped at 100)
223
+ * Down: -30 points (auto-flag if result < 40)
224
+ *
225
+ * @param projectRoot - The root directory of the project
226
+ * @param entryPath - Relative path to the entry from the wiki directory
227
+ * @param direction - 'up' to increase confidence, 'down' to decrease
228
+ * @returns The updated WikiEntry
229
+ * @throws Error if entry not found
230
+ */
231
+ function adjustConfidence(projectRoot, entryPath, direction) {
232
+ const entry = (0, entry_js_1.readEntry)(projectRoot, entryPath);
233
+ if (!entry) {
234
+ throw new Error(`Entry not found: ${entryPath}`);
235
+ }
236
+ const currentConfidence = entry.frontmatter.confidence;
237
+ let newConfidence;
238
+ if (direction === 'up') {
239
+ newConfidence = Math.min(currentConfidence + 20, types_js_1.CONFIDENCE.MAX);
240
+ }
241
+ else {
242
+ newConfidence = Math.max(currentConfidence - 30, types_js_1.CONFIDENCE.MIN);
243
+ }
244
+ // Only update if confidence actually changed
245
+ if (newConfidence === currentConfidence) {
246
+ return entry;
247
+ }
248
+ // Auto-flag if confidence drops below threshold
249
+ const shouldFlag = direction === 'down' && newConfidence < types_js_1.CONFIDENCE.THRESHOLD;
250
+ return (0, entry_js_1.updateEntry)(projectRoot, entryPath, {
251
+ confidence: newConfidence,
252
+ ...(shouldFlag ? { status: 'flagged' } : {})
253
+ }, {
254
+ by: 'claude',
255
+ context: `confidence adjusted ${direction}`,
256
+ reason: `Confidence changed from ${currentConfidence} to ${newConfidence}${shouldFlag ? ' (auto-flagged: below threshold)' : ''}`
257
+ });
258
+ }
259
+ /**
260
+ * Marks that a solution from an entry worked, increasing its confidence.
261
+ *
262
+ * @param projectRoot - The root directory of the project
263
+ * @param entryPath - Relative path to the entry from the wiki directory
264
+ * @returns The updated WikiEntry
265
+ */
266
+ function markSolutionWorked(projectRoot, entryPath) {
267
+ const entry = (0, entry_js_1.readEntry)(projectRoot, entryPath);
268
+ if (!entry) {
269
+ throw new Error(`Entry not found: ${entryPath}`);
270
+ }
271
+ // Increase confidence
272
+ const updatedEntry = adjustConfidence(projectRoot, entryPath, 'up');
273
+ // Add a validated audit entry if confidence changed
274
+ if (updatedEntry.frontmatter.confidence !== entry.frontmatter.confidence) {
275
+ return (0, entry_js_1.updateEntry)(projectRoot, entryPath, {}, {
276
+ by: 'claude',
277
+ context: 'solution-validated',
278
+ reason: 'Solution worked successfully'
279
+ });
280
+ }
281
+ return updatedEntry;
282
+ }
283
+ /**
284
+ * Marks that a solution from an entry failed, decreasing its confidence.
285
+ * Auto-flags if confidence drops below threshold (handled by adjustConfidence).
286
+ *
287
+ * @param projectRoot - The root directory of the project
288
+ * @param entryPath - Relative path to the entry from the wiki directory
289
+ * @returns The updated WikiEntry
290
+ */
291
+ function markSolutionFailed(projectRoot, entryPath) {
292
+ // Decrease confidence (auto-flags if below threshold)
293
+ return adjustConfidence(projectRoot, entryPath, 'down');
294
+ }
295
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,110 @@
1
+ // hooks/error-lookup.ts
2
+ import {
3
+ wikiExists,
4
+ matchTrigger,
5
+ getBestMatch,
6
+ WikiEntry,
7
+ CONFIDENCE,
8
+ ErrorLookupOutput,
9
+ SearchResult,
10
+ validateErrorLookupInput,
11
+ ValidationError,
12
+ ErrorLookupContext
13
+ } from '../src/index.js';
14
+
15
+ /**
16
+ * Extracts the solution section from wiki entry content.
17
+ */
18
+ function extractSolution(content: string): string {
19
+ // Look for Solution heading
20
+ const solutionMatch = content.match(/## Solution\n([\s\S]*?)(?=\n## |$)/);
21
+ if (solutionMatch) {
22
+ return solutionMatch[1].trim().slice(0, 200) + '...';
23
+ }
24
+ // Fallback: first 200 chars
25
+ return content.slice(0, 200) + '...';
26
+ }
27
+
28
+ export async function onErrorLookup(input: unknown): Promise<ErrorLookupOutput | null> {
29
+ try {
30
+ // Validate input first
31
+ const validatedInput = validateErrorLookupInput(input);
32
+ const { projectRoot, errorText, toolResult } = validatedInput;
33
+
34
+ // Get error text from either direct input or tool stderr
35
+ const error = errorText || toolResult?.stderr || '';
36
+
37
+ if (!error || !wikiExists(projectRoot)) {
38
+ return null;
39
+ }
40
+
41
+ // Try to match error against trigger patterns
42
+ const results = await matchTrigger(projectRoot, error);
43
+ const bestMatch = getBestMatch(results);
44
+
45
+ if (bestMatch && bestMatch.entry.frontmatter.confidence >= CONFIDENCE.THRESHOLD) {
46
+ // Record usage for analytics
47
+ try {
48
+ const { recordEntryUsage } = await import('../src/index.js');
49
+ recordEntryUsage(projectRoot, bestMatch.entry.path);
50
+ } catch {
51
+ // Usage tracking failure is non-critical
52
+ }
53
+
54
+ // Output for Claude Code hook integration (user-facing console logs)
55
+ console.log(`📚 Solvdex found a solution:`);
56
+ console.log(` "${bestMatch.entry.frontmatter.title}"`);
57
+ console.log(` Confidence: ${bestMatch.entry.frontmatter.confidence}`);
58
+ console.log(` `);
59
+ console.log(` Solution: ${extractSolution(bestMatch.entry.content)}`);
60
+
61
+ // Structured output for Claude Code (includes both old and new format for backward compatibility)
62
+ const output: ErrorLookupOutput = {
63
+ // Old format (for backward compatibility)
64
+ type: 'wiki_solution',
65
+ message: `Wiki: Found "${bestMatch.entry.frontmatter.title}" (confidence: ${bestMatch.entry.frontmatter.confidence})`,
66
+ entry: bestMatch.entry,
67
+ // New format (Claude Code integration)
68
+ continue: true,
69
+ hookSpecificOutput: {
70
+ type: 'solution_found',
71
+ message: `Found solution: "${bestMatch.entry.frontmatter.title}"`,
72
+ entries: [{
73
+ title: bestMatch.entry.frontmatter.title,
74
+ category: bestMatch.entry.category,
75
+ path: bestMatch.entry.path,
76
+ confidence: bestMatch.entry.frontmatter.confidence
77
+ }]
78
+ },
79
+ additionalContext: formatSolutionForContext(bestMatch)
80
+ };
81
+
82
+ // Output JSON marker + JSON (MUST be last output)
83
+ console.log('\n__HOOK_OUTPUT__');
84
+ console.log(JSON.stringify(output));
85
+
86
+ return output;
87
+ }
88
+
89
+ return null;
90
+ } catch (error) {
91
+ // Handle validation errors separately
92
+ if (error instanceof ValidationError) {
93
+ console.error(`[Solvdex] Invalid input: ${error.message}`);
94
+ return null;
95
+ }
96
+ // Graceful degradation - log error but don't crash
97
+ console.error(`[Solvdex] Error in error-lookup hook: ${error instanceof Error ? error.message : 'Unknown error'}`);
98
+ return null;
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Formats a solution match into a readable context string for Claude Code.
104
+ */
105
+ function formatSolutionForContext(match: SearchResult): string {
106
+ const e = match.entry;
107
+ return `## ${e.frontmatter.title} (${e.category})\nConfidence: ${e.frontmatter.confidence}\n\n${e.content}`;
108
+ }
109
+
110
+ export default onErrorLookup;
@@ -0,0 +1,49 @@
1
+ {
2
+ "description": "Solvdex wiki hooks for auto-capture and retrieval",
3
+ "hooks": {
4
+ "SessionStart": [
5
+ {
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "${CLAUDE_PLUGIN_ROOT}/scripts/session-start.py",
10
+ "timeout": 30
11
+ }
12
+ ]
13
+ }
14
+ ],
15
+ "UserPromptSubmit": [
16
+ {
17
+ "hooks": [
18
+ {
19
+ "type": "command",
20
+ "command": "${CLAUDE_PLUGIN_ROOT}/scripts/prompt-enrich.py",
21
+ "timeout": 30
22
+ }
23
+ ]
24
+ }
25
+ ],
26
+ "PostToolUseFailure": [
27
+ {
28
+ "hooks": [
29
+ {
30
+ "type": "command",
31
+ "command": "${CLAUDE_PLUGIN_ROOT}/scripts/error-lookup.py",
32
+ "timeout": 30
33
+ }
34
+ ]
35
+ }
36
+ ],
37
+ "Stop": [
38
+ {
39
+ "hooks": [
40
+ {
41
+ "type": "command",
42
+ "command": "${CLAUDE_PLUGIN_ROOT}/scripts/post-task.py",
43
+ "timeout": 30
44
+ }
45
+ ]
46
+ }
47
+ ]
48
+ }
49
+ }