@kjerneverk/execution-anthropic 1.0.4-dev.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 (42) hide show
  1. package/.kodrdriv-test-cache.json +6 -0
  2. package/LICENSE +18 -0
  3. package/README.md +83 -0
  4. package/dist/index.d.ts +85 -0
  5. package/dist/index.js +123 -0
  6. package/dist/index.js.map +1 -0
  7. package/output/kodrdriv/.kodrdriv-parallel-context.json +584 -0
  8. package/output/kodrdriv/.kodrdriv-parallel-context.json.lock +2 -0
  9. package/output/kodrdriv/260110-1741-release-notes.md +36 -0
  10. package/output/kodrdriv/260112-2201-commit-message.md +1 -0
  11. package/output/kodrdriv/260112-2202-release-notes.md +39 -0
  12. package/output/kodrdriv/260112-2340-commit-message.md +1 -0
  13. package/output/kodrdriv/260113-0022-commit-message.md +1 -0
  14. package/output/kodrdriv/260113-0023-release-notes.md +45 -0
  15. package/output/kodrdriv/260114-0655-commit-message.md +5 -0
  16. package/output/kodrdriv/260115-0616-commit-message.md +4 -0
  17. package/output/kodrdriv/260115-0739-commit-message.md +1 -0
  18. package/output/kodrdriv/260126-0919-commit-message.md +1 -0
  19. package/output/kodrdriv/260126-0921-release-notes.md +34 -0
  20. package/output/kodrdriv/260128-0923-commit-message.md +3 -0
  21. package/output/kodrdriv/260128-0924-release-notes.md +23 -0
  22. package/output/kodrdriv/260130-1638-commit-message.md +1 -0
  23. package/output/kodrdriv/260130-1645-commit-message.md +1 -0
  24. package/output/kodrdriv/260130-1646-release-notes.md +30 -0
  25. package/output/kodrdriv/RELEASE_NOTES.md +28 -0
  26. package/output/kodrdriv/RELEASE_TITLE.md +1 -0
  27. package/output/kodrdriv/agentic-reflection-commit-2026-01-13T06-01-28-797Z.md +97 -0
  28. package/output/kodrdriv/agentic-reflection-commit-2026-01-13T07-40-49-371Z.md +97 -0
  29. package/output/kodrdriv/agentic-reflection-commit-2026-01-13T08-22-38-911Z.md +97 -0
  30. package/output/kodrdriv/agentic-reflection-commit-2026-01-14T14-55-30-939Z.md +118 -0
  31. package/output/kodrdriv/agentic-reflection-commit-2026-01-15T14-16-26-349Z.md +117 -0
  32. package/output/kodrdriv/agentic-reflection-commit-2026-01-15T15-39-45-943Z.md +97 -0
  33. package/output/kodrdriv/agentic-reflection-commit-2026-01-26T17-19-48-407Z.md +188 -0
  34. package/output/kodrdriv/agentic-reflection-commit-2026-01-31T00-38-51-441Z.md +160 -0
  35. package/output/kodrdriv/agentic-reflection-commit-2026-01-31T00-45-53-143Z.md +130 -0
  36. package/output/kodrdriv/agentic-reflection-release-2026-01-11T01-41-03-039Z.md +330 -0
  37. package/output/kodrdriv/agentic-reflection-release-2026-01-13T06-02-11-920Z.md +270 -0
  38. package/output/kodrdriv/agentic-reflection-release-2026-01-13T08-23-08-625Z.md +299 -0
  39. package/output/kodrdriv/agentic-reflection-release-2026-01-26T17-21-17-390Z.md +365 -0
  40. package/output/kodrdriv/agentic-reflection-release-2026-01-31T00-46-16-542Z.md +362 -0
  41. package/package.json +57 -0
  42. package/package.json~ +56 -0
@@ -0,0 +1,330 @@
1
+ # Agentic Workflow - Self-Reflection Report
2
+
3
+ Generated: 2026-01-11T01:41:03.039Z
4
+
5
+ ## Execution Summary
6
+
7
+ - **Iterations**: 5
8
+ - **Tool Calls**: 12
9
+ - **Unique Tools**: 7
10
+
11
+ ## Tool Effectiveness Analysis
12
+
13
+ | Tool | Calls | Success | Failures | Success Rate | Avg Duration |
14
+ |------|-------|---------|----------|--------------|--------------|
15
+ | get_file_content | 6 | 6 | 0 | 100.0% | 0ms |
16
+ | search_codebase | 2 | 1 | 1 | 50.0% | 13ms |
17
+ | get_breaking_changes | 1 | 1 | 0 | 100.0% | 24ms |
18
+ | get_release_stats | 1 | 1 | 0 | 100.0% | 43ms |
19
+ | analyze_commit_patterns | 1 | 1 | 0 | 100.0% | 9ms |
20
+ | get_tag_history | 1 | 1 | 0 | 100.0% | 23ms |
21
+ | compare_previous_release | 1 | 1 | 0 | 100.0% | 36ms |
22
+
23
+ ### Tool Performance Insights
24
+
25
+ **Tools with Failures:**
26
+ - search_codebase: 1/2 failures (50.0%)
27
+
28
+ **Most Frequently Used:**
29
+ - get_breaking_changes: 1 calls
30
+ - get_release_stats: 1 calls
31
+ - analyze_commit_patterns: 1 calls
32
+
33
+ ## Recommendations for Improvement
34
+
35
+ - **Tool Failures**: Investigate and fix tools that are failing. This may indicate issues with error handling or tool implementation.
36
+ - **Underutilized Tools**: Many tools were called only once. Consider whether all tools are necessary or if the agent needs better guidance on when to use them.
37
+
38
+ ## Detailed Execution Timeline
39
+
40
+ | Time | Iteration | Tool | Result | Duration |
41
+ |------|-----------|------|--------|----------|
42
+ | 5:40:07 PM | 1 | get_breaking_changes | ✅ Success | 24ms |
43
+ | 5:40:07 PM | 1 | get_release_stats | ✅ Success | 43ms |
44
+ | 5:40:07 PM | 1 | analyze_commit_patterns | ✅ Success | 9ms |
45
+ | 5:40:07 PM | 1 | get_tag_history | ✅ Success | 23ms |
46
+ | 5:40:18 PM | 2 | get_file_content | ✅ Success | 1ms |
47
+ | 5:40:18 PM | 2 | get_file_content | ✅ Success | 0ms |
48
+ | 5:40:18 PM | 2 | get_file_content | ✅ Success | 0ms |
49
+ | 5:40:18 PM | 2 | search_codebase | ❌ Tool "search_codebase" execution failed: Search failed: Command failed: git grep -n -C 2 "src/index.test.ts"
50
+ | 14ms |
51
+ | 5:40:18 PM | 2 | search_codebase | ✅ Success | 12ms |
52
+ | 5:40:32 PM | 3 | compare_previous_release | ✅ Success | 36ms |
53
+ | 5:40:34 PM | 4 | get_file_content | ✅ Success | 0ms |
54
+ | 5:40:34 PM | 4 | get_file_content | ✅ Success | 0ms |
55
+ | 5:40:34 PM | 4 | get_file_content | ✅ Success | 0ms |
56
+
57
+ ## Conversation History
58
+
59
+ <details>
60
+ <summary>Click to expand full agentic interaction</summary>
61
+
62
+ ```json
63
+ [
64
+ {
65
+ "role": "system",
66
+ "content": "You are a professional software engineer writing release notes for your team and users.\n\n## Available Tools\n\n### General\n\n**get_file_history**\nGet git commit history for one or more files to understand their evolution and past changes\n\nParameters:\n- `filePaths` (required): Array of file paths to get history for\n- `limit`: Maximum number of commits to return (default: 10)\n- `format`: Output format: \"summary\" for brief or \"detailed\" for full messages\n\n**When to use:** Get git commit history for one or more files to understand their evolution and past changes\n\n---\n\n**get_file_content**\nGet the complete current content of a file to understand context around changes. Returns a message if the file does not exist (e.g., if it was deleted).\n\nParameters:\n- `filePath` (required): Path to the file\n- `includeLineNumbers`: Include line numbers in output (default: false)\n\n**When to use:** Get the complete current content of a file to understand context around changes. Returns a message if the file does not exist (e.g., if it was deleted).\n\n---\n\n**search_codebase**\nSearch for code patterns, function names, or text across the codebase using git grep\n\nParameters:\n- `query` (required): Search pattern (can be plain text or regex)\n- `fileTypes`: Limit search to specific file extensions (e.g., [\"ts\", \"js\"])\n- `contextLines`: Number of context lines to show around matches (default: 2)\n\n**When to use:** Search for code patterns, function names, or text across the codebase using git grep\n\n---\n\n**get_related_tests**\nFind test files related to production files to understand what the code is supposed to do\n\nParameters:\n- `filePaths` (required): Production file paths\n\n**When to use:** Find test files related to production files to understand what the code is supposed to do\n\n---\n\n**get_file_dependencies**\nFind which files import or depend on the changed files to assess change impact\n\nParameters:\n- `filePaths` (required): Files to analyze dependencies for\n\n**When to use:** Find which files import or depend on the changed files to assess change impact\n\n---\n\n**analyze_diff_section**\nGet expanded context around specific lines in a file to better understand changes\n\nParameters:\n- `filePath` (required): File containing the section to analyze\n- `startLine` (required): Starting line number\n- `endLine` (required): Ending line number\n- `contextLines`: Number of additional context lines to show before and after (default: 10)\n\n**When to use:** Get expanded context around specific lines in a file to better understand changes\n\n---\n\n**get_recent_commits**\nGet recent commits that modified the same files to understand recent work in this area\n\nParameters:\n- `filePaths` (required): Files to check for recent commits\n- `since`: Time period to look back (e.g., \"1 week ago\", \"2 days ago\")\n- `limit`: Maximum number of commits to return (default: 5)\n\n**When to use:** Get recent commits that modified the same files to understand recent work in this area\n\n---\n\n**group_files_by_concern**\nAnalyze changed files and suggest logical groupings that might represent separate concerns\n\nParameters:\n- `filePaths` (required): All changed files to analyze\n\n**When to use:** Analyze changed files and suggest logical groupings that might represent separate concerns\n\n---\n\n### Release Analysis\n\n**get_tag_history** _(cheap)_\nGet the history of previous release tags to understand release patterns and versioning\n\nParameters:\n- `limit`: Number of recent tags to retrieve (default: 10)\n- `pattern`: Filter tags by pattern (e.g., \"v*\" for version tags)\n\n**When to use:** Get the history of previous release tags to understand release patterns and versioning\n\n**Examples:**\n- Check recent version tags: `get_tag_history({\"limit\":5,\"pattern\":\"v*\"})`\n\n---\n\n**compare_previous_release** _(moderate)_\nCompare this release with a previous release to understand what changed between versions\n\nParameters:\n- `previousTag` (required): Previous release tag to compare against\n- `currentRef`: Current reference (default: HEAD)\n- `statsOnly`: Return only statistics, not full diff (default: true)\n\n**When to use:** Compare this release with a previous release to understand what changed between versions\n\n**Examples:**\n- Compare with last release: `compare_previous_release({\"previousTag\":\"v1.0.0\",\"currentRef\":\"HEAD\"})`\n\n---\n\n**get_release_stats** _(moderate)_\nGet comprehensive statistics about the release including contributors, file changes, and commit patterns\n\nParameters:\n- `fromRef` (required): Starting reference for the release range\n- `toRef`: Ending reference for the release range (default: HEAD)\n\n**When to use:** Get comprehensive statistics about the release including contributors, file changes, and commit patterns\n\n**Examples:**\n- Get release overview: `get_release_stats({\"fromRef\":\"v1.0.0\",\"toRef\":\"HEAD\"})`\n\n---\n\n**get_breaking_changes** _(expensive)_\nSearch for potential breaking changes by looking for specific patterns in commits and diffs\n\nParameters:\n- `fromRef` (required): Starting reference for the release range\n- `toRef`: Ending reference for the release range (default: HEAD)\n\n**When to use:** Search for potential breaking changes by looking for specific patterns in commits and diffs\n\n**Examples:**\n- Check for breaking changes: `get_breaking_changes({\"fromRef\":\"v1.0.0\",\"toRef\":\"HEAD\"})`\n\n---\n\n**analyze_commit_patterns** _(cheap)_\nAnalyze commit messages to identify patterns and themes in the release\n\nParameters:\n- `fromRef` (required): Starting reference for the release range\n- `toRef`: Ending reference for the release range (default: HEAD)\n\n**When to use:** Analyze commit messages to identify patterns and themes in the release\n\n**Examples:**\n- Find commit themes: `analyze_commit_patterns({\"fromRef\":\"v1.0.0\",\"toRef\":\"HEAD\"})`\n\n---\n\n\n\n## Your Task\n\nWrite release notes that clearly explain what's in this release and why it matters. Your notes should help users and developers understand what changed without needing to read every commit.\n\nFocus on:\n- What problems does this release solve?\n- What new capabilities does it add?\n- What's the impact on users and developers?\n- Are there breaking changes or important considerations?\n\nUse the available tools to investigate the changes. The more you understand, the better your notes will be.\n\n**Important**: If additional context is provided (from context files or other sources), use your judgment:\n- If the context is relevant to this specific package/release, incorporate it appropriately\n- If the context describes changes in other packages or unrelated work, ignore it\n- Don't fabricate connections between this package and unrelated context\n- Be honest about what changed - only mention what actually happened in this release\n- Context is supplemental information, not a requirement to include\n\n## Investigation Approach\n\nUse tools based on what you need to know:\n\n**Context:**\n- get_tag_history - understand release patterns\n- get_release_stats - quantify scope\n- compare_previous_release - see how this compares\n\n**Understanding:**\n- group_files_by_concern - identify themes\n- analyze_commit_patterns - detect patterns\n- get_file_content - see full context\n- analyze_diff_section - expand unclear changes\n- get_file_history - understand evolution\n\n**Impact:**\n- get_file_dependencies - assess reach\n- search_codebase - find usage patterns\n- get_related_tests - understand behavior changes\n- get_breaking_changes - identify breaking changes (always use)\n\n## Writing Style\n\nWrite naturally and directly:\n- Use plain language that users can understand\n- Be specific about what changed and why\n- Avoid marketing speak and buzzwords\n- No emojis or excessive punctuation\n- No phrases like \"we're excited to announce\"\n- No meta-commentary about the release itself\n- Focus on facts and implications, not enthusiasm\n\nStructure your notes logically:\n- Start with the most important changes\n- Group related changes together\n- Explain breaking changes clearly\n- Include practical examples when helpful\n\n## Output Format\n\nWhen ready, format your response as JSON:\n\nRELEASE_NOTES:\n{\n \"title\": \"Clear, factual title describing the main changes\",\n \"body\": \"Detailed release notes in Markdown format\"\n}\n\nOutput only the JSON. No conversational remarks or follow-up offers."
67
+ },
68
+ {
69
+ "role": "user",
70
+ "content": "I need comprehensive release notes for changes from main to HEAD.\n\n## Commit Log\ncommit 9fe4385eeb70851b53cd75744dcf9fbd6de5fa02\nAuthor: Tim O'Brien <tobrien@discursive.com>\nDate: Sat Jan 10 13:18:04 2026 -0800\n\n Updated and separated tests\n\ncommit c99b06505aa201b8a5c9a3cea2a9e5fe1f59450b\nAuthor: Tim O'Brien <tobrien@discursive.com>\nDate: Sat Jan 10 11:23:15 2026 -0800\n\n 0.0.2-dev.0\n\n\n## Diff Summary\ndiff --git a/.kodrdriv-test-cache.json b/.kodrdriv-test-cache.json\nindex e57a3f0..e6ff88b 100644\n--- a/.kodrdriv-test-cache.json\n+++ b/.kodrdriv-test-cache.json\n@@ -1,6 +1,6 @@\n {\n \"/Users/tobrien/gitw/kjerneverk/execution-anthropic\": {\n- \"lastTestRun\": 1768072522781,\n- \"lastCommitHash\": \"unknown\"\n+ \"lastTestRun\": 1768074147459,\n+ \"lastCommitHash\": \"c99b06505aa201b8a5c9a3cea2a9e5fe1f59450b\"\n }\n }\n\\ndiff --git a/package.json b/package.json\nindex b9e6fd2..e970b38 100644\n--- a/package.json\n+++ b/package.json\n@@ -1,6 +1,6 @@\n {\n \"name\": \"@riotprompt/execution-anthropic\",\n- \"version\": \"0.0.1\",\n+ \"version\": \"0.0.2\",\n \"description\": \"Anthropic Claude provider for execution interface\",\n \"type\": \"module\",\n \"main\": \"./dist/index.cjs\",\n@@ -14,9 +14,13 @@\n }\n },\n \"scripts\": {\n+ \"clean\": \"rm -rf dist\",\n \"build\": \"vite build\",\n- \"test\": \"vitest run\",\n- \"lint\": \"eslint src\"\n+ \"test\": \"vitest run --coverage\",\n+ \"test:coverage\": \"vitest run --coverage\",\n+ \"lint\": \"eslint src\",\n+ \"precommit\": \"npm run lint && npm run test\",\n+ \"prepublishOnly\": \"npm run clean && npm run build\"\n },\n \"keywords\": [\n \"llm\",\n@@ -27,6 +31,10 @@\n ],\n \"author\": \"Tim O'Brien <tobrien@discursive.com>\",\n \"license\": \"Apache-2.0\",\n+ \"repository\": {\n+ \"type\": \"git\",\n+ \"url\": \"https://github.com/kjerneverk/execution-anthropic\"\n+ },\n \"dependencies\": {\n \"@anthropic-ai/sdk\": \"^0.52.0\"\n },\n@@ -34,6 +42,7 @@\n \"@types/node\": \"^25.0.6\",\n \"@typescript-eslint/eslint-plugin\": \"^8.33.1\",\n \"@typescript-eslint/parser\": \"^8.33.1\",\n+ \"@vitest/coverage-v8\": \"^3.2.4\",\n \"eslint\": \"^9.28.0\",\n \"globals\": \"^16.2.0\",\n \"typescript\": \"^5.8.3\",\ndiff --git a/src/index.test.ts b/tests/index.test.ts\nsimilarity index 99%\nrename from src/index.test.ts\nrename to tests/index.test.ts\nindex d2b309d..7522c63 100644\n--- a/src/index.test.ts\n+++ b/tests/index.test.ts\n@@ -12,7 +12,7 @@ import {\n type ExecutionOptions,\n type ProviderResponse,\n type Provider,\n-} from './index.js';\n+} from '../src/index.js';\n \n describe('AnthropicProvider', () => {\n let provider: AnthropicProvider;\ndiff --git a/vitest.config.ts b/vitest.config.ts\nindex 05da292..c6f4053 100644\n--- a/vitest.config.ts\n+++ b/vitest.config.ts\n@@ -2,8 +2,20 @@ import { defineConfig } from \"vitest/config\";\n \n export default defineConfig({\n test: {\n- include: [\"src/**/*.test.ts\", \"tests/**/*.test.ts\"],\n+ include: [\"tests/**/*.test.ts\"],\n globals: true,\n+ coverage: {\n+ provider: \"v8\",\n+ reporter: [\"text\", \"json\", \"html\"],\n+ include: [\"src/**/*.ts\"],\n+ exclude: [\n+ \"src/**/*.test.ts\",\n+ \"node_modules/\",\n+ \"dist/**\",\n+ \"vitest.config.ts\",\n+ \"vite.config.ts\",\n+ \"eslint.config.mjs\",\n+ ],\n+ },\n },\n });\n-\n\n\nAnalyze these changes and write clear release notes. Consider:\n- What's the main story of this release?\n- What problems does it solve?\n- What's the impact on users and developers?\n- Are there breaking changes?\n\nIf context information is provided, use it only if relevant to this specific package.\nDon't force connections that don't exist - if context describes changes in other packages\nor unrelated features, simply ignore it and focus on what actually changed in this release.\n\nInvestigate as needed to write accurate, helpful release notes."
71
+ },
72
+ {
73
+ "role": "assistant",
74
+ "content": null,
75
+ "tool_calls": [
76
+ {
77
+ "id": "call_Tg15wfL8OiYsc3LDlull4yN4",
78
+ "type": "function",
79
+ "function": {
80
+ "name": "get_breaking_changes",
81
+ "arguments": "{\"fromRef\": \"main\", \"toRef\": \"HEAD\"}"
82
+ }
83
+ },
84
+ {
85
+ "id": "call_LY1wd0e5h17iosmCXPOhMgxQ",
86
+ "type": "function",
87
+ "function": {
88
+ "name": "get_release_stats",
89
+ "arguments": "{\"fromRef\": \"main\", \"toRef\": \"HEAD\"}"
90
+ }
91
+ },
92
+ {
93
+ "id": "call_KbJSzlohmONCjVXO5NzgtSOj",
94
+ "type": "function",
95
+ "function": {
96
+ "name": "analyze_commit_patterns",
97
+ "arguments": "{\"fromRef\": \"main\", \"toRef\": \"HEAD\"}"
98
+ }
99
+ },
100
+ {
101
+ "id": "call_i9x3fbcUMboRIcJC6Bz6OLy2",
102
+ "type": "function",
103
+ "function": {
104
+ "name": "get_tag_history",
105
+ "arguments": "{\"limit\": 10, \"pattern\": \"v*\"}"
106
+ }
107
+ }
108
+ ]
109
+ },
110
+ {
111
+ "role": "tool",
112
+ "tool_call_id": "call_Tg15wfL8OiYsc3LDlull4yN4",
113
+ "content": "No obvious breaking changes detected. Manual review recommended for API changes.",
114
+ "name": "get_breaking_changes"
115
+ },
116
+ {
117
+ "role": "tool",
118
+ "tool_call_id": "call_LY1wd0e5h17iosmCXPOhMgxQ",
119
+ "content": "Total commits: 2\n\nContributors:\n 2\tTim O'Brien\n\n\nFile changes: 5 files changed, 633 insertions(+), 12 deletions(-)\n\nTop 10 most changed files:\n vitest.config.ts | 16 +-\n package.json | 15 +-\n package-lock.json | 608 ++++++++++++++++++++++++++++++++++++++++++-\n 5 files changed, 633 insertions(+), 12 deletions(-)\n {src => tests}/index.test.ts | 2 +-\n .kodrdriv-test-cache.json | 4 +-\n",
120
+ "name": "get_release_stats"
121
+ },
122
+ {
123
+ "role": "tool",
124
+ "tool_call_id": "call_KbJSzlohmONCjVXO5NzgtSOj",
125
+ "content": "\nTop keywords in commits:\n updated: 1\n separated: 1\n tests: 1",
126
+ "name": "analyze_commit_patterns"
127
+ },
128
+ {
129
+ "role": "tool",
130
+ "tool_call_id": "call_i9x3fbcUMboRIcJC6Bz6OLy2",
131
+ "content": "Recent release tags:\nv0.0.2-dev.0: tag v0.0.2-dev.0\nTagger: Tim O'Brien <tobrien@discursive.com>\n\n0.0.2-dev.0\n2026-01-10 11:23:15 -0800 - 0.0.2-dev.0",
132
+ "name": "get_tag_history"
133
+ },
134
+ {
135
+ "role": "assistant",
136
+ "content": null,
137
+ "tool_calls": [
138
+ {
139
+ "id": "call_GygiHNGlfC3bMZF4xv6pykcn",
140
+ "type": "function",
141
+ "function": {
142
+ "name": "get_file_content",
143
+ "arguments": "{\"filePath\": \"package.json\"}"
144
+ }
145
+ },
146
+ {
147
+ "id": "call_PllnkhHGL2dTdf1KCwq2we5G",
148
+ "type": "function",
149
+ "function": {
150
+ "name": "get_file_content",
151
+ "arguments": "{\"filePath\": \"vitest.config.ts\"}"
152
+ }
153
+ },
154
+ {
155
+ "id": "call_rCzLPl6ORsl5DkfNG1VgtFtt",
156
+ "type": "function",
157
+ "function": {
158
+ "name": "get_file_content",
159
+ "arguments": "{\"filePath\": \"tests/index.test.ts\"}"
160
+ }
161
+ },
162
+ {
163
+ "id": "call_Y3TdYdgyd0q5JZI4M9aZWOEI",
164
+ "type": "function",
165
+ "function": {
166
+ "name": "search_codebase",
167
+ "arguments": "{\"query\": \"src/index.test.ts\", \"contextLines\": 2}"
168
+ }
169
+ },
170
+ {
171
+ "id": "call_8J0SCLOZ1bi4zBtMlUYED4tO",
172
+ "type": "function",
173
+ "function": {
174
+ "name": "search_codebase",
175
+ "arguments": "{\"query\": \"describe('AnthropicProvider'\", \"contextLines\": 2}"
176
+ }
177
+ }
178
+ ]
179
+ },
180
+ {
181
+ "role": "tool",
182
+ "tool_call_id": "call_GygiHNGlfC3bMZF4xv6pykcn",
183
+ "content": "{\n \"name\": \"@riotprompt/execution-anthropic\",\n \"version\": \"0.0.2\",\n \"description\": \"Anthropic Claude provider for execution interface\",\n \"type\": \"module\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n }\n },\n \"scripts\": {\n \"clean\": \"rm -rf dist\",\n \"build\": \"vite build\",\n \"test\": \"vitest run --coverage\",\n \"test:coverage\": \"vitest run --coverage\",\n \"lint\": \"eslint src\",\n \"precommit\": \"npm run lint && npm run test\",\n \"prepublishOnly\": \"npm run clean && npm run build\"\n },\n \"keywords\": [\n \"llm\",\n \"anthropic\",\n \"claude\",\n \"execution\",\n \"provider\"\n ],\n \"author\": \"Tim O'Brien <tobrien@discursive.com>\",\n \"license\": \"Apache-2.0\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/kjerneverk/execution-anthropic\"\n },\n \"dependencies\": {\n \"@anthropic-ai/sdk\": \"^0.52.0\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^25.0.6\",\n \"@typescript-eslint/eslint-plugin\": \"^8.33.1\",\n \"@typescript-eslint/parser\": \"^8.33.1\",\n \"@vitest/coverage-v8\": \"^3.2.4\",\n \"eslint\": \"^9.28.0\",\n \"globals\": \"^16.2.0\",\n \"typescript\": \"^5.8.3\",\n \"vite\": \"^7.0.4\",\n \"vite-plugin-dts\": \"^4.5.4\",\n \"vitest\": \"^3.2.4\"\n }\n}\n",
184
+ "name": "get_file_content"
185
+ },
186
+ {
187
+ "role": "tool",
188
+ "tool_call_id": "call_PllnkhHGL2dTdf1KCwq2we5G",
189
+ "content": "import { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n test: {\n include: [\"tests/**/*.test.ts\"],\n globals: true,\n coverage: {\n provider: \"v8\",\n reporter: [\"text\", \"json\", \"html\"],\n include: [\"src/**/*.ts\"],\n exclude: [\n \"src/**/*.test.ts\",\n \"node_modules/\",\n \"dist/**\",\n \"vitest.config.ts\",\n \"vite.config.ts\",\n \"eslint.config.mjs\",\n ],\n },\n },\n});\n",
190
+ "name": "get_file_content"
191
+ },
192
+ {
193
+ "role": "tool",
194
+ "tool_call_id": "call_rCzLPl6ORsl5DkfNG1VgtFtt",
195
+ "content": "/**\n * Tests for execution-anthropic package\n */\n\nimport { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';\nimport {\n AnthropicProvider,\n createAnthropicProvider,\n VERSION,\n type Message,\n type Request,\n type ExecutionOptions,\n type ProviderResponse,\n type Provider,\n} from '../src/index.js';\n\ndescribe('AnthropicProvider', () => {\n let provider: AnthropicProvider;\n\n beforeEach(() => {\n provider = new AnthropicProvider();\n });\n\n describe('name', () => {\n it('should have name \"anthropic\"', () => {\n expect(provider.name).toBe('anthropic');\n });\n });\n\n describe('supportsModel', () => {\n it('should support Claude 3 models', () => {\n expect(provider.supportsModel('claude-3-opus-20240229')).toBe(true);\n expect(provider.supportsModel('claude-3-sonnet-20240229')).toBe(true);\n expect(provider.supportsModel('claude-3-haiku-20240307')).toBe(true);\n });\n\n it('should support Claude 3.5 models', () => {\n expect(provider.supportsModel('claude-3-5-sonnet-20240620')).toBe(true);\n expect(provider.supportsModel('claude-3-5-haiku-20241022')).toBe(true);\n });\n\n it('should support Claude 4 models', () => {\n expect(provider.supportsModel('claude-4-opus')).toBe(true);\n expect(provider.supportsModel('claude-sonnet-4-20250514')).toBe(true);\n });\n\n it('should not support GPT models', () => {\n expect(provider.supportsModel('gpt-4')).toBe(false);\n expect(provider.supportsModel('gpt-4o')).toBe(false);\n expect(provider.supportsModel('gpt-3.5-turbo')).toBe(false);\n });\n\n it('should not support Gemini models', () => {\n expect(provider.supportsModel('gemini-1.5-pro')).toBe(false);\n expect(provider.supportsModel('gemini-1.5-flash')).toBe(false);\n });\n\n it('should return false for empty/undefined model', () => {\n expect(provider.supportsModel('')).toBe(false);\n });\n });\n\n describe('execute', () => {\n const originalEnv = process.env;\n\n beforeEach(() => {\n process.env = { ...originalEnv };\n delete process.env.ANTHROPIC_API_KEY;\n });\n\n afterEach(() => {\n process.env = originalEnv;\n });\n\n it('should throw error when no API key is provided', async () => {\n const request: Request = {\n messages: [{ role: 'user', content: 'Hello' }],\n model: 'claude-3-opus-20240229',\n addMessage: vi.fn(),\n };\n\n await expect(provider.execute(request)).rejects.toThrow(\n 'Anthropic API key is required'\n );\n });\n\n it('should throw error when API key is empty string', async () => {\n const request: Request = {\n messages: [{ role: 'user', content: 'Hello' }],\n model: 'claude-3-opus-20240229',\n addMessage: vi.fn(),\n };\n\n await expect(provider.execute(request, { apiKey: '' })).rejects.toThrow(\n 'Anthropic API key is required'\n );\n });\n });\n\n describe('implements Provider interface', () => {\n it('should satisfy Provider interface', () => {\n const p: Provider = provider;\n expect(p.name).toBe('anthropic');\n expect(typeof p.execute).toBe('function');\n expect(typeof p.supportsModel).toBe('function');\n });\n });\n});\n\ndescribe('createAnthropicProvider', () => {\n it('should create a new AnthropicProvider instance', () => {\n const provider = createAnthropicProvider();\n expect(provider).toBeInstanceOf(AnthropicProvider);\n expect(provider.name).toBe('anthropic');\n });\n});\n\ndescribe('VERSION', () => {\n it('should export version string', () => {\n expect(VERSION).toBe('0.0.1');\n });\n});\n\ndescribe('Type exports', () => {\n it('should export Message type', () => {\n const msg: Message = {\n role: 'user',\n content: 'Hello',\n };\n expect(msg.role).toBe('user');\n expect(msg.content).toBe('Hello');\n });\n\n it('should support all message roles', () => {\n const roles: Message['role'][] = ['user', 'assistant', 'system', 'developer', 'tool'];\n roles.forEach(role => {\n const msg: Message = { role, content: 'test' };\n expect(msg.role).toBe(role);\n });\n });\n\n it('should support array content', () => {\n const msg: Message = {\n role: 'user',\n content: ['Hello', 'World'],\n };\n expect(Array.isArray(msg.content)).toBe(true);\n });\n\n it('should support null content', () => {\n const msg: Message = {\n role: 'assistant',\n content: null,\n };\n expect(msg.content).toBeNull();\n });\n\n it('should support optional name field', () => {\n const msg: Message = {\n role: 'user',\n content: 'Hello',\n name: 'test-user',\n };\n expect(msg.name).toBe('test-user');\n });\n\n it('should export ExecutionOptions type', () => {\n const opts: ExecutionOptions = {\n apiKey: 'test-key',\n model: 'claude-3-opus-20240229',\n temperature: 0.7,\n maxTokens: 1000,\n timeout: 30000,\n retries: 3,\n };\n expect(opts.apiKey).toBe('test-key');\n expect(opts.temperature).toBe(0.7);\n });\n\n it('should export ProviderResponse type', () => {\n const response: ProviderResponse = {\n content: 'Hello!',\n model: 'claude-3-opus-20240229',\n usage: {\n inputTokens: 10,\n outputTokens: 5,\n },\n };\n expect(response.content).toBe('Hello!');\n expect(response.usage?.inputTokens).toBe(10);\n });\n\n it('should support toolCalls in ProviderResponse', () => {\n const response: ProviderResponse = {\n content: '',\n model: 'claude-3-opus-20240229',\n toolCalls: [\n {\n id: 'call_123',\n type: 'function',\n function: {\n name: 'get_weather',\n arguments: '{\"location\": \"NYC\"}',\n },\n },\n ],\n };\n expect(response.toolCalls).toHaveLength(1);\n expect(response.toolCalls?.[0].function.name).toBe('get_weather');\n });\n});\n\n",
196
+ "name": "get_file_content"
197
+ },
198
+ {
199
+ "role": "tool",
200
+ "tool_call_id": "call_Y3TdYdgyd0q5JZI4M9aZWOEI",
201
+ "content": "Tool execution failed: Tool \"search_codebase\" execution failed: Search failed: Command failed: git grep -n -C 2 \"src/index.test.ts\"\n",
202
+ "name": "search_codebase"
203
+ },
204
+ {
205
+ "role": "tool",
206
+ "tool_call_id": "call_8J0SCLOZ1bi4zBtMlUYED4tO",
207
+ "content": "tests/index.test.ts-15-} from '../src/index.js';\ntests/index.test.ts-16-\ntests/index.test.ts:17:describe('AnthropicProvider', () => {\ntests/index.test.ts-18- let provider: AnthropicProvider;\ntests/index.test.ts-19-\n",
208
+ "name": "search_codebase"
209
+ },
210
+ {
211
+ "role": "assistant",
212
+ "content": null,
213
+ "tool_calls": [
214
+ {
215
+ "id": "call_6eIeJ5KNAtnqZtavYMgYfcK7",
216
+ "type": "function",
217
+ "function": {
218
+ "name": "compare_previous_release",
219
+ "arguments": "{\"previousTag\":\"main\",\"currentRef\":\"HEAD\",\"statsOnly\":false}"
220
+ }
221
+ }
222
+ ]
223
+ },
224
+ {
225
+ "role": "tool",
226
+ "tool_call_id": "call_6eIeJ5KNAtnqZtavYMgYfcK7",
227
+ "content": "Comparison between main and HEAD:\n\nCommits: 2\n\nFile changes:\n .kodrdriv-test-cache.json | 4 +-\n package-lock.json | 608 ++++++++++++++++++++++++++++++++++++++++++-\n package.json | 15 +-\n {src => tests}/index.test.ts | 2 +-\n vitest.config.ts | 16 +-\n 5 files changed, 633 insertions(+), 12 deletions(-)\n\n\nCommit summary:\n9fe4385 Updated and separated tests\nc99b065 0.0.2-dev.0\n",
228
+ "name": "compare_previous_release"
229
+ },
230
+ {
231
+ "role": "assistant",
232
+ "content": null,
233
+ "tool_calls": [
234
+ {
235
+ "id": "call_3DLtJHPEk5hYUJJVnHY0Ewf1",
236
+ "type": "function",
237
+ "function": {
238
+ "name": "get_file_content",
239
+ "arguments": "{\"filePath\": \"src/index.js\"}"
240
+ }
241
+ },
242
+ {
243
+ "id": "call_2tCDXu0AM8donWeSDGBTouG5",
244
+ "type": "function",
245
+ "function": {
246
+ "name": "get_file_content",
247
+ "arguments": "{\"filePath\": \"src/index.ts\"}"
248
+ }
249
+ },
250
+ {
251
+ "id": "call_YzDUbqmgJnIlGIjIXAJ4G4WI",
252
+ "type": "function",
253
+ "function": {
254
+ "name": "get_file_content",
255
+ "arguments": "{\"filePath\": \"src/index.ts\", \"includeLineNumbers\": true}"
256
+ }
257
+ }
258
+ ]
259
+ },
260
+ {
261
+ "role": "tool",
262
+ "tool_call_id": "call_3DLtJHPEk5hYUJJVnHY0Ewf1",
263
+ "content": "File not found: src/index.js\n\nThis file may have been deleted in this release or does not exist in the current working tree. Check the diff to see if this file was removed.",
264
+ "name": "get_file_content"
265
+ },
266
+ {
267
+ "role": "tool",
268
+ "tool_call_id": "call_2tCDXu0AM8donWeSDGBTouG5",
269
+ "content": "/**\n * Execution Anthropic Package\n *\n * Anthropic provider implementation for LLM execution.\n *\n * @packageDocumentation\n */\n\nimport Anthropic from '@anthropic-ai/sdk';\n\n// ===== INLINE TYPES (from 'execution' package) =====\n\nexport type Model = string;\n\nexport interface Message {\n role: 'user' | 'assistant' | 'system' | 'developer' | 'tool';\n content: string | string[] | null;\n name?: string;\n}\n\nexport interface Request {\n messages: Message[];\n model: Model;\n responseFormat?: any;\n validator?: any;\n addMessage(message: Message): void;\n}\n\nexport interface ProviderResponse {\n content: string;\n model: string;\n usage?: {\n inputTokens: number;\n outputTokens: number;\n };\n toolCalls?: Array<{\n id: string;\n type: 'function';\n function: {\n name: string;\n arguments: string;\n };\n }>;\n}\n\nexport interface ExecutionOptions {\n apiKey?: string;\n model?: string;\n temperature?: number;\n maxTokens?: number;\n timeout?: number;\n retries?: number;\n}\n\nexport interface Provider {\n readonly name: string;\n execute(request: Request, options?: ExecutionOptions): Promise<ProviderResponse>;\n supportsModel?(model: Model): boolean;\n}\n\n/**\n * Anthropic Provider implementation\n */\nexport class AnthropicProvider implements Provider {\n readonly name = 'anthropic';\n\n /**\n * Check if this provider supports a given model\n */\n supportsModel(model: Model): boolean {\n if (!model) return false;\n return model.startsWith('claude');\n }\n\n /**\n * Execute a request against Anthropic\n */\n async execute(\n request: Request,\n options: ExecutionOptions = {}\n ): Promise<ProviderResponse> {\n const apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY;\n if (!apiKey) throw new Error('Anthropic API key is required');\n\n const client = new Anthropic({ apiKey });\n\n const model = options.model || request.model || 'claude-3-opus-20240229';\n\n // Anthropic separates system prompt from messages\n let systemPrompt = '';\n const messages: Anthropic.MessageParam[] = [];\n\n for (const msg of request.messages) {\n if (msg.role === 'system' || msg.role === 'developer') {\n systemPrompt +=\n (typeof msg.content === 'string'\n ? msg.content\n : JSON.stringify(msg.content)) + '\\n\\n';\n } else {\n messages.push({\n role: msg.role as 'user' | 'assistant',\n content:\n typeof msg.content === 'string'\n ? msg.content\n : JSON.stringify(msg.content),\n });\n }\n }\n\n const response = await client.messages.create({\n model: model,\n system: systemPrompt.trim() || undefined,\n messages: messages,\n max_tokens: options.maxTokens || 4096,\n temperature: options.temperature,\n ...(request.responseFormat?.type === 'json_schema'\n ? {\n tools: [\n {\n name: request.responseFormat.json_schema.name,\n description:\n request.responseFormat.json_schema.description ||\n 'Output data in this structured format',\n input_schema:\n request.responseFormat.json_schema.schema,\n },\n ],\n tool_choice: {\n type: 'tool' as const,\n name: request.responseFormat.json_schema.name,\n },\n }\n : {}),\n });\n\n // Handle ContentBlock\n let text = '';\n\n if (request.responseFormat?.type === 'json_schema') {\n const toolUseBlock = response.content.find(\n (block) => block.type === 'tool_use'\n );\n if (toolUseBlock && toolUseBlock.type === 'tool_use') {\n text = JSON.stringify(toolUseBlock.input, null, 2);\n }\n } else {\n const contentBlock = response.content[0];\n text = contentBlock.type === 'text' ? contentBlock.text : '';\n }\n\n return {\n content: text,\n model: response.model,\n usage: {\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n },\n };\n }\n}\n\n/**\n * Create a new Anthropic provider instance\n */\nexport function createAnthropicProvider(): AnthropicProvider {\n return new AnthropicProvider();\n}\n\n/**\n * Package version\n */\nexport const VERSION = '0.0.1';\n\nexport default AnthropicProvider;\n",
270
+ "name": "get_file_content"
271
+ },
272
+ {
273
+ "role": "tool",
274
+ "tool_call_id": "call_YzDUbqmgJnIlGIjIXAJ4G4WI",
275
+ "content": "1: /**\n2: * Execution Anthropic Package\n3: *\n4: * Anthropic provider implementation for LLM execution.\n5: *\n6: * @packageDocumentation\n7: */\n8: \n9: import Anthropic from '@anthropic-ai/sdk';\n10: \n11: // ===== INLINE TYPES (from 'execution' package) =====\n12: \n13: export type Model = string;\n14: \n15: export interface Message {\n16: role: 'user' | 'assistant' | 'system' | 'developer' | 'tool';\n17: content: string | string[] | null;\n18: name?: string;\n19: }\n20: \n21: export interface Request {\n22: messages: Message[];\n23: model: Model;\n24: responseFormat?: any;\n25: validator?: any;\n26: addMessage(message: Message): void;\n27: }\n28: \n29: export interface ProviderResponse {\n30: content: string;\n31: model: string;\n32: usage?: {\n33: inputTokens: number;\n34: outputTokens: number;\n35: };\n36: toolCalls?: Array<{\n37: id: string;\n38: type: 'function';\n39: function: {\n40: name: string;\n41: arguments: string;\n42: };\n43: }>;\n44: }\n45: \n46: export interface ExecutionOptions {\n47: apiKey?: string;\n48: model?: string;\n49: temperature?: number;\n50: maxTokens?: number;\n51: timeout?: number;\n52: retries?: number;\n53: }\n54: \n55: export interface Provider {\n56: readonly name: string;\n57: execute(request: Request, options?: ExecutionOptions): Promise<ProviderResponse>;\n58: supportsModel?(model: Model): boolean;\n59: }\n60: \n61: /**\n62: * Anthropic Provider implementation\n63: */\n64: export class AnthropicProvider implements Provider {\n65: readonly name = 'anthropic';\n66: \n67: /**\n68: * Check if this provider supports a given model\n69: */\n70: supportsModel(model: Model): boolean {\n71: if (!model) return false;\n72: return model.startsWith('claude');\n73: }\n74: \n75: /**\n76: * Execute a request against Anthropic\n77: */\n78: async execute(\n79: request: Request,\n80: options: ExecutionOptions = {}\n81: ): Promise<ProviderResponse> {\n82: const apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY;\n83: if (!apiKey) throw new Error('Anthropic API key is required');\n84: \n85: const client = new Anthropic({ apiKey });\n86: \n87: const model = options.model || request.model || 'claude-3-opus-20240229';\n88: \n89: // Anthropic separates system prompt from messages\n90: let systemPrompt = '';\n91: const messages: Anthropic.MessageParam[] = [];\n92: \n93: for (const msg of request.messages) {\n94: if (msg.role === 'system' || msg.role === 'developer') {\n95: systemPrompt +=\n96: (typeof msg.content === 'string'\n97: ? msg.content\n98: : JSON.stringify(msg.content)) + '\\n\\n';\n99: } else {\n100: messages.push({\n101: role: msg.role as 'user' | 'assistant',\n102: content:\n103: typeof msg.content === 'string'\n104: ? msg.content\n105: : JSON.stringify(msg.content),\n106: });\n107: }\n108: }\n109: \n110: const response = await client.messages.create({\n111: model: model,\n112: system: systemPrompt.trim() || undefined,\n113: messages: messages,\n114: max_tokens: options.maxTokens || 4096,\n115: temperature: options.temperature,\n116: ...(request.responseFormat?.type === 'json_schema'\n117: ? {\n118: tools: [\n119: {\n120: name: request.responseFormat.json_schema.name,\n121: description:\n122: request.responseFormat.json_schema.description ||\n123: 'Output data in this structured format',\n124: input_schema:\n125: request.responseFormat.json_schema.schema,\n126: },\n127: ],\n128: tool_choice: {\n129: type: 'tool' as const,\n130: name: request.responseFormat.json_schema.name,\n131: },\n132: }\n133: : {}),\n134: });\n135: \n136: // Handle ContentBlock\n137: let text = '';\n138: \n139: if (request.responseFormat?.type === 'json_schema') {\n140: const toolUseBlock = response.content.find(\n141: (block) => block.type === 'tool_use'\n142: );\n143: if (toolUseBlock && toolUseBlock.type === 'tool_use') {\n144: text = JSON.stringify(toolUseBlock.input, null, 2);\n145: }\n146: } else {\n147: const contentBlock = response.content[0];\n148: text = contentBlock.type === 'text' ? contentBlock.text : '';\n149: }\n150: \n151: return {\n152: content: text,\n153: model: response.model,\n154: usage: {\n155: inputTokens: response.usage.input_tokens,\n156: outputTokens: response.usage.output_tokens,\n157: },\n158: };\n159: }\n160: }\n161: \n162: /**\n163: * Create a new Anthropic provider instance\n164: */\n165: export function createAnthropicProvider(): AnthropicProvider {\n166: return new AnthropicProvider();\n167: }\n168: \n169: /**\n170: * Package version\n171: */\n172: export const VERSION = '0.0.1';\n173: \n174: export default AnthropicProvider;\n175: ",
276
+ "name": "get_file_content"
277
+ },
278
+ {
279
+ "role": "assistant",
280
+ "content": "RELEASE_NOTES:\n{\n \"title\": \"v0.0.2: Test suite moved to /tests, coverage enabled by default, and improved publish workflow\",\n \"body\": \"## Summary\\nThis update is primarily a **developer workflow / CI** release. The runtime provider implementation under `src/` is unchanged, but tests and tooling were reorganized to make releases and quality checks more consistent.\\n\\n## Changes\\n### Testing: separated tests from source\\n- Moved `src/index.test.ts` to `tests/index.test.ts`.\\n- Updated Vitest to only discover tests under `tests/**/*.test.ts` (no longer scanning `src/**/*.test.ts`).\\n\\n**Why it matters:** keeps test files out of the source tree (and out of build/packaging paths), and makes test discovery more predictable.\\n\\n### Coverage: enabled and configured\\n- `npm test` now runs `vitest run --coverage` (coverage is generated by default).\\n- Added `@vitest/coverage-v8` and configured coverage reporting:\\n - Provider: `v8`\\n - Reporters: `text`, `json`, `html`\\n - Coverage includes `src/**/*.ts` and excludes `dist/**`, config files, `node_modules/`, and test files.\\n\\n**Impact:** test runs will typically be a bit slower, but you now get consistent coverage output locally and in CI.\\n\\n### Scripts: cleaner precommit and publishing flow\\n- Added `clean` script (`rm -rf dist`).\\n- Added `precommit`: runs lint + tests (`npm run lint && npm run test`).\\n- Added `prepublishOnly`: ensures a clean, fresh build before publishing (`npm run clean && npm run build`).\\n\\n### Package metadata\\n- Version bumped to `0.0.2` in `package.json`.\\n- Added `repository` metadata for npm/GitHub linking.\\n\\n## Breaking changes\\n- **No runtime/API breaking changes** were introduced.\\n- **Developer-facing change:** if you had tests under `src/**/*.test.ts`, they will no longer run by default. Move them to `tests/` or update `vitest.config.ts`.\\n\\n## Notes / known issues\\n- The exported `VERSION` constant in `src/index.ts` still reports `0.0.1` while `package.json` is `0.0.2`. If you rely on `VERSION` at runtime, be aware this value is currently out of sync.\"\n}"
281
+ }
282
+ ]
283
+ ```
284
+
285
+ </details>
286
+
287
+ ## Generated Release Notes
288
+
289
+ ### Title
290
+ ```
291
+ v0.0.2: Test suite moved to /tests, coverage enabled by default, and improved publish workflow
292
+ ```
293
+
294
+ ### Body
295
+ ```markdown
296
+ ## Summary
297
+ This update is primarily a **developer workflow / CI** release. The runtime provider implementation under `src/` is unchanged, but tests and tooling were reorganized to make releases and quality checks more consistent.
298
+
299
+ ## Changes
300
+ ### Testing: separated tests from source
301
+ - Moved `src/index.test.ts` to `tests/index.test.ts`.
302
+ - Updated Vitest to only discover tests under `tests/**/*.test.ts` (no longer scanning `src/**/*.test.ts`).
303
+
304
+ **Why it matters:** keeps test files out of the source tree (and out of build/packaging paths), and makes test discovery more predictable.
305
+
306
+ ### Coverage: enabled and configured
307
+ - `npm test` now runs `vitest run --coverage` (coverage is generated by default).
308
+ - Added `@vitest/coverage-v8` and configured coverage reporting:
309
+ - Provider: `v8`
310
+ - Reporters: `text`, `json`, `html`
311
+ - Coverage includes `src/**/*.ts` and excludes `dist/**`, config files, `node_modules/`, and test files.
312
+
313
+ **Impact:** test runs will typically be a bit slower, but you now get consistent coverage output locally and in CI.
314
+
315
+ ### Scripts: cleaner precommit and publishing flow
316
+ - Added `clean` script (`rm -rf dist`).
317
+ - Added `precommit`: runs lint + tests (`npm run lint && npm run test`).
318
+ - Added `prepublishOnly`: ensures a clean, fresh build before publishing (`npm run clean && npm run build`).
319
+
320
+ ### Package metadata
321
+ - Version bumped to `0.0.2` in `package.json`.
322
+ - Added `repository` metadata for npm/GitHub linking.
323
+
324
+ ## Breaking changes
325
+ - **No runtime/API breaking changes** were introduced.
326
+ - **Developer-facing change:** if you had tests under `src/**/*.test.ts`, they will no longer run by default. Move them to `tests/` or update `vitest.config.ts`.
327
+
328
+ ## Notes / known issues
329
+ - The exported `VERSION` constant in `src/index.ts` still reports `0.0.1` while `package.json` is `0.0.2`. If you rely on `VERSION` at runtime, be aware this value is currently out of sync.
330
+ ```