git-impact 0.3.0 → 0.6.3

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 (71) hide show
  1. package/README.md +125 -78
  2. package/dist/cli/index.js +32 -211
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/init/installer.d.ts +6 -0
  5. package/dist/init/installer.d.ts.map +1 -1
  6. package/dist/init/installer.js +58 -5
  7. package/dist/init/installer.js.map +1 -1
  8. package/dist/init/installer.test.d.ts +2 -0
  9. package/dist/init/installer.test.d.ts.map +1 -0
  10. package/dist/init/installer.test.js +127 -0
  11. package/dist/init/installer.test.js.map +1 -0
  12. package/dist/init/templates.d.ts +8 -7
  13. package/dist/init/templates.d.ts.map +1 -1
  14. package/dist/init/templates.js +73 -371
  15. package/dist/init/templates.js.map +1 -1
  16. package/dist/mcp/repo.d.ts +8 -3
  17. package/dist/mcp/repo.d.ts.map +1 -1
  18. package/dist/mcp/repo.js +27 -9
  19. package/dist/mcp/repo.js.map +1 -1
  20. package/dist/mcp/repo.test.d.ts +2 -0
  21. package/dist/mcp/repo.test.d.ts.map +1 -0
  22. package/dist/mcp/repo.test.js +133 -0
  23. package/dist/mcp/repo.test.js.map +1 -0
  24. package/dist/mcp/resources.js +0 -1
  25. package/dist/mcp/resources.js.map +1 -1
  26. package/dist/mcp/tools.d.ts.map +1 -1
  27. package/dist/mcp/tools.js +100 -12
  28. package/dist/mcp/tools.js.map +1 -1
  29. package/dist/mcp/tools.test.d.ts +2 -0
  30. package/dist/mcp/tools.test.d.ts.map +1 -0
  31. package/dist/mcp/tools.test.js +123 -0
  32. package/dist/mcp/tools.test.js.map +1 -0
  33. package/dist/readers/git.d.ts +2 -1
  34. package/dist/readers/git.d.ts.map +1 -1
  35. package/dist/readers/git.js +12 -6
  36. package/dist/readers/git.js.map +1 -1
  37. package/dist/readers/redact.d.ts +29 -0
  38. package/dist/readers/redact.d.ts.map +1 -0
  39. package/dist/readers/redact.js +82 -0
  40. package/dist/readers/redact.js.map +1 -0
  41. package/dist/readers/redact.test.d.ts +2 -0
  42. package/dist/readers/redact.test.d.ts.map +1 -0
  43. package/dist/readers/redact.test.js +72 -0
  44. package/dist/readers/redact.test.js.map +1 -0
  45. package/dist/report/html.d.ts +2 -0
  46. package/dist/report/html.d.ts.map +1 -1
  47. package/dist/report/html.js +35 -1
  48. package/dist/report/html.js.map +1 -1
  49. package/dist/report/render.d.ts.map +1 -1
  50. package/dist/report/render.js +2 -0
  51. package/dist/report/render.js.map +1 -1
  52. package/dist/storage/db.d.ts +23 -2
  53. package/dist/storage/db.d.ts.map +1 -1
  54. package/dist/storage/db.js +12 -0
  55. package/dist/storage/db.js.map +1 -1
  56. package/dist/storage/db.test.d.ts +2 -0
  57. package/dist/storage/db.test.d.ts.map +1 -0
  58. package/dist/storage/db.test.js +152 -0
  59. package/dist/storage/db.test.js.map +1 -0
  60. package/package.json +7 -6
  61. package/skill/SKILL.md +142 -205
  62. package/skill/references/html-template.md +131 -0
  63. package/skill/references/translation-rules.md +87 -0
  64. package/dist/translator/prompt.d.ts +0 -21
  65. package/dist/translator/prompt.d.ts.map +0 -1
  66. package/dist/translator/prompt.js +0 -117
  67. package/dist/translator/prompt.js.map +0 -1
  68. package/dist/translator/translate.d.ts +0 -36
  69. package/dist/translator/translate.d.ts.map +0 -1
  70. package/dist/translator/translate.js +0 -73
  71. package/dist/translator/translate.js.map +0 -1
@@ -0,0 +1,131 @@
1
+ # HTML presentation guide
2
+
3
+ Read this file ONLY when composing today's bespoke HTML presentation. The
4
+ `renderReport` MCP-side renderer handles the rolling dashboard at
5
+ `.git-impact/result.html` automatically — this file is for the *daily artifact*
6
+ the user can share as a screenshot or paste-into-Slack visual.
7
+
8
+ ## Where to write
9
+
10
+ Use your `Write` tool to create:
11
+ - `<repo>/.git-impact/standups/YYYY-MM-DD.html` — today's bespoke file
12
+ - `<repo>/.git-impact/standups/index.html` — list of all standups (regenerate)
13
+
14
+ ## Stack (all CDN — no install)
15
+
16
+ | Tool | URL | When to use |
17
+ |---|---|---|
18
+ | Tailwind CSS | `<script src="https://cdn.tailwindcss.com"></script>` | Always |
19
+ | Inter font | `https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap` | Always |
20
+ | Chart.js | `https://cdn.jsdelivr.net/npm/chart.js` | Only if there are real numbers worth charting |
21
+ | Mermaid | `https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs` | Only for architecture/flow diagrams when relevant |
22
+ | Lucide icons | `https://unpkg.com/lucide@latest` | Optional — call `lucide.createIcons()` after DOM ready |
23
+
24
+ Don't include all of them. Pick what the day's content actually needs.
25
+
26
+ ## Required structure
27
+
28
+ 1. **Hero** — date label + a bold, plain-English headline that captures the day.
29
+ "Shipped safety analytics, hardened tenant isolation" — NOT "9 commits today".
30
+ 2. **Stats grid** — 3-4 metric cards (commits, files, PRs merged, areas touched).
31
+ 3. **Achievement cards** — one per ✅ item with status pill, title, summary,
32
+ "→ Why it matters" line, and small chips: PR #, area, file count, plus an
33
+ "inferred" chip when the bullet's provenance is `inferred`.
34
+ 4. **Optional visual** — only if the content warrants one:
35
+ - Mermaid flow diagram for architecture/data-flow changes
36
+ - Chart.js for ratios/comparisons
37
+ - Code block for a key formula or snippet
38
+ - Skip entirely if the day was straightforward — don't force visuals.
39
+ 5. **Footer** — file count, commit count, branch, link back to `index.html`.
40
+
41
+ ## Design language
42
+
43
+ - **Theme:** dark by default (`bg-slate-950`), generous spacing, max width 4xl
44
+ - **Cards:** `bg-slate-900/50 border border-slate-800 rounded-2xl p-6`
45
+ - **Status pills:**
46
+ - ✅ Shipped → `bg-emerald-500/20 text-emerald-400`
47
+ - ⏳ In Progress → `bg-amber-500/20 text-amber-400`
48
+ - 🚫 Blocked → `bg-rose-500/20 text-rose-400`
49
+ - **Inferred chip:** `bg-amber-500/10 text-amber-300/70 border border-amber-500/30`
50
+ with title attribute "Impact inferred — not explicitly stated in PR or commit"
51
+ - **Print-friendly:** include `@media print { ... }` that hides nav and switches to light theme
52
+ - **Spacing:** `max-w-4xl mx-auto px-8 py-12`, `space-y-6` between cards
53
+ - **Typography:** Inter, tight letter-spacing on headlines, 1.6 line-height on body
54
+
55
+ ## Skeleton (adapt content to today's actual work)
56
+
57
+ ```html
58
+ <!doctype html>
59
+ <html lang="en">
60
+ <head>
61
+ <meta charset="utf-8" />
62
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
63
+ <title>Standup — [Day, Date] · [Repo]</title>
64
+ <script src="https://cdn.tailwindcss.com"></script>
65
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
66
+ <style>
67
+ body { font-family: 'Inter', system-ui, sans-serif; }
68
+ @media print { .no-print { display: none } body { background: white; color: black; } }
69
+ </style>
70
+ </head>
71
+ <body class="bg-slate-950 text-slate-100 min-h-screen">
72
+ <div class="absolute inset-0 bg-[radial-gradient(circle_at_top,rgba(56,189,248,0.08),transparent_50%)] pointer-events-none"></div>
73
+
74
+ <main class="relative max-w-4xl mx-auto px-8 py-16">
75
+ <header class="mb-16">
76
+ <p class="text-sm uppercase tracking-widest text-slate-500 font-medium">[Saturday, May 9, 2026]</p>
77
+ <h1 class="mt-3 text-5xl font-bold tracking-tight leading-tight">[Headline that captures the day]</h1>
78
+ <p class="mt-4 text-xl text-slate-400 max-w-2xl">[One-sentence subtitle]</p>
79
+ </header>
80
+
81
+ <section class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-16">
82
+ <div class="bg-slate-900/50 border border-slate-800 rounded-2xl p-5">
83
+ <div class="text-3xl font-bold">[N]</div>
84
+ <div class="text-sm text-slate-400 mt-1">commits</div>
85
+ </div>
86
+ <!-- ... 3 more stat cards -->
87
+ </section>
88
+
89
+ <section class="space-y-4 mb-16">
90
+ <h2 class="text-xs uppercase tracking-widest text-slate-500 font-semibold mb-4">Shipped today</h2>
91
+ <article class="bg-slate-900/50 border border-slate-800 rounded-2xl p-6">
92
+ <div class="flex items-start gap-4">
93
+ <span class="px-2 py-1 rounded-md bg-emerald-500/20 text-emerald-400 text-xs font-medium">✅ Shipped</span>
94
+ <div class="flex-1">
95
+ <h3 class="text-lg font-semibold">[Plain-English title]</h3>
96
+ <p class="text-slate-300 mt-2 leading-relaxed">[One-sentence summary]</p>
97
+ <p class="text-slate-400 mt-3 text-sm">→ [Why it matters in business terms]</p>
98
+ <div class="flex gap-2 mt-4 flex-wrap">
99
+ <span class="text-xs px-2 py-0.5 rounded-full border border-slate-700 text-slate-400">PR #142</span>
100
+ <!-- Add an inferred chip when provenance === "inferred" -->
101
+ <span class="text-xs px-2 py-0.5 rounded-full bg-amber-500/10 text-amber-300/70 border border-amber-500/30" title="Impact inferred">inferred</span>
102
+ </div>
103
+ </div>
104
+ </div>
105
+ </article>
106
+ </section>
107
+
108
+ <footer class="pt-8 border-t border-slate-800 text-sm text-slate-500 flex justify-between">
109
+ <span>[N] files · [N] commits · [branch]</span>
110
+ <a href="./index.html" class="hover:text-slate-300">← All standups</a>
111
+ </footer>
112
+ </main>
113
+ </body>
114
+ </html>
115
+ ```
116
+
117
+ ## Index page
118
+
119
+ `<repo>/.git-impact/standups/index.html` should list every daily HTML file
120
+ (newest first). Same dark theme, simple grid of cards each linking to its day.
121
+ Keep it lightweight — don't re-render everything, just enumerate files.
122
+
123
+ ## Final line
124
+
125
+ After writing both files, print exactly this on the LAST line of your reply:
126
+
127
+ ```
128
+ 🎯 file:///<repo-absolute-path>/.git-impact/standups/YYYY-MM-DD.html
129
+ ```
130
+
131
+ Use the real absolute path so the user can ⌘-click.
@@ -0,0 +1,87 @@
1
+ # Translation rules
2
+
3
+ Read this file when translating commits into impact bullets. The main `SKILL.md`
4
+ covers orchestration; this file owns the prompt-engineering details.
5
+
6
+ ## Core rules
7
+
8
+ 1. **What + why, not what + how.** Each bullet must say what was accomplished
9
+ AND why it matters. "Fixed a bug in the auth middleware" is useless to a
10
+ manager. "Fixed login failures for admin users — unblocks the Q2 portal
11
+ launch" is useful.
12
+
13
+ 2. **Apply the glossary.** Replace every term in `context.json`'s `glossary`
14
+ with its plain-English equivalent. If no glossary exists, infer from
15
+ context but stay non-jargon.
16
+
17
+ 3. **Provenance is mandatory.** Every bullet you save via `save_impact_entry`
18
+ MUST include a `provenance` value. Use the strongest source available:
19
+
20
+ | Provenance | When to use |
21
+ |---|---|
22
+ | `pr` | The "why" came from the linked PR description body |
23
+ | `commit_body` | The "why" came from a multi-line commit message body (after the subject) |
24
+ | `commit_message` | The "why" was visible in the commit subject line itself |
25
+ | `ticket` | The "why" came from a linked Linear/Jira/GitHub issue |
26
+ | `inferred` | You guessed the impact without explicit text supporting it |
27
+
28
+ **Never label something `pr` or `commit_body` if you actually inferred it.**
29
+ Inferred is honest; faking provenance is worse than admitting a guess.
30
+
31
+ 4. **Group related commits.** Three commits all touching auth tell one story.
32
+ Write one bullet, not three. The grouping should follow the user's
33
+ *narrative*, not just shared paths — two commits in `/auth/` may be unrelated.
34
+
35
+ 5. **WIP / draft commits** get `status: "in_progress"` and the bullet should
36
+ describe the **expected outcome** when complete, not what was done so far.
37
+ "Refactoring auth flow → will reduce login latency by ~40%" beats
38
+ "WIP: extracted middleware function".
39
+
40
+ 6. **Blocked work** gets `status: "blocked"`. Use this when a commit is
41
+ reverted, a branch is abandoned, or the user explicitly says "stuck on X".
42
+
43
+ 7. **Be specific with numbers.** "Improved performance" is vague.
44
+ "Reduced login latency by ~40%" is specific. Pull numbers from commit
45
+ messages, PR descriptions, or diff stats. Don't invent them.
46
+
47
+ 8. **Refs help reviewers trust you.** When you have them, populate the `refs`
48
+ array: `["PR #142", "a1b2c3d", "ENG-1234"]`. These show as small chips in
49
+ the HTML report and let a reader click through to verify.
50
+
51
+ ## Output format (for the user-facing text reply)
52
+
53
+ ```
54
+ 📅 [Day, Date]
55
+
56
+ ✅ [Plain-English summary of what was accomplished]
57
+ → [Why it matters — who it unblocks, what risk it reduces, what it enables]
58
+
59
+ ⏳ In progress: [What is being worked on]
60
+ → [Expected outcome when complete]
61
+
62
+ 🚫 Blocked: [What is stuck]
63
+ → [What's needed to unblock]
64
+
65
+ 📁 [N] files changed across [brief description of areas touched]
66
+ [N] commit(s) on [branch name]
67
+ ```
68
+
69
+ If a bullet is `inferred`, the HTML report will mark it with an "inferred"
70
+ chip automatically — you don't need to do anything special in the text reply.
71
+
72
+ ## Tone
73
+
74
+ - Write for a non-technical manager. No jargon that isn't in the glossary.
75
+ - Short sentences. No filler. Skip "this change" / "this commit" constructions.
76
+ - Confident — if you know the impact, state it. If you don't, label it
77
+ `inferred` and use phrases like "technical foundation work for X". Never
78
+ hedge with "might potentially" or "could possibly".
79
+ - 2 accurate bullets beat 5 vague ones.
80
+
81
+ ## Anti-patterns
82
+
83
+ - ❌ Restating commit messages verbatim ("refactor: extract middleware")
84
+ - ❌ Inventing impact you can't ground in the data ("saves 10 hours per week")
85
+ - ❌ Mixing provenance — one bullet pulled from PR + one from inference labeled the same way
86
+ - ❌ Using `done` status when the work is genuinely in progress
87
+ - ❌ Writing 5+ bullets to look productive — pick the 2-3 that actually mattered
@@ -1,21 +0,0 @@
1
- import { GitSummary } from "../readers/git";
2
- import { GitHubSummary } from "../readers/github";
3
- import { UserContext } from "../storage/db";
4
- export interface TranslateInput {
5
- git: GitSummary;
6
- github: GitHubSummary | null;
7
- context: UserContext | null;
8
- dateLabel: string;
9
- }
10
- export declare function buildPrompt(input: TranslateInput): string;
11
- export declare function buildReviewPrompt(entries: Array<{
12
- date: string;
13
- items: Array<{
14
- status: string;
15
- summary: string;
16
- impact: string;
17
- }>;
18
- totalCommits: number;
19
- repoName: string;
20
- }>, context: UserContext | null, periodLabel: string): string;
21
- //# sourceMappingURL=prompt.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/translator/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,UAAU,CAAC;IAChB,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAmFzD;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,KAAK,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClE,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,EACF,OAAO,EAAE,WAAW,GAAG,IAAI,EAC3B,WAAW,EAAE,MAAM,GAClB,MAAM,CAyCR"}
@@ -1,117 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.buildPrompt = buildPrompt;
4
- exports.buildReviewPrompt = buildReviewPrompt;
5
- function buildPrompt(input) {
6
- const { git, github, context, dateLabel } = input;
7
- const contextBlock = context
8
- ? `
9
- ## Company & Role Context
10
- ${context.companyDescription ? `Company: ${context.companyDescription}` : ""}
11
- ${context.managerPriorities ? `Manager priorities: ${context.managerPriorities}` : ""}
12
- ${context.glossary && Object.keys(context.glossary).length > 0
13
- ? `Technical term translations:\n${Object.entries(context.glossary)
14
- .map(([term, meaning]) => ` - ${term} = ${meaning}`)
15
- .join("\n")}`
16
- : ""}
17
- `.trim()
18
- : "";
19
- const commitsBlock = git.commits
20
- .map((c) => `- [${c.hash}] ${c.message}${c.body ? `\n ${c.body.split("\n")[0]}` : ""}${c.filesChanged.length > 0
21
- ? `\n Files: ${c.filesChanged.slice(0, 8).join(", ")}${c.filesChanged.length > 8 ? ` (+${c.filesChanged.length - 8} more)` : ""}`
22
- : ""}`)
23
- .join("\n");
24
- const githubBlock = github
25
- ? `
26
- ## GitHub Activity
27
- Repo: ${github.repoFullName}
28
-
29
- PRs Opened Today: ${github.prsOpened.length > 0 ? github.prsOpened.map((pr) => `#${pr.number} "${pr.title}"${pr.body ? ` — ${pr.body.slice(0, 100)}` : ""}`).join(", ") : "none"}
30
-
31
- PRs Merged Today: ${github.prsMerged.length > 0 ? github.prsMerged.map((pr) => `#${pr.number} "${pr.title}"`).join(", ") : "none"}
32
-
33
- PRs Reviewed Today: ${github.prsReviewed.length > 0 ? github.prsReviewed.map((pr) => `#${pr.number} "${pr.title}"`).join(", ") : "none"}
34
- `.trim()
35
- : "";
36
- return `You are a technical writing assistant. Your job is to translate a developer's git activity into plain-English business impact for their daily standup or manager update.
37
-
38
- ${contextBlock}
39
-
40
- ## Git Activity for ${dateLabel}
41
- Repo: ${git.repoName} (branch: ${git.branch})
42
- Total files changed: ${git.totalFilesChanged}
43
-
44
- Commits:
45
- ${commitsBlock || "No commits found"}
46
-
47
- ${githubBlock}
48
-
49
- ## Your Task
50
- Translate the above technical work into 2–5 bullet points that a non-technical manager or stakeholder can understand.
51
-
52
- Rules:
53
- 1. Each bullet must describe WHAT was accomplished and WHY it matters to the business. Never just restate the commit message.
54
- 2. Use the glossary to replace jargon (e.g. "RLS" → the meaning provided). If no glossary, infer plain English from context.
55
- 3. If you can't confidently infer business impact, say what was done technically but don't invent a business outcome — use phrasing like "technical foundation work".
56
- 4. For in-progress work (WIP commits, draft PRs), mark as "In progress" with expected outcome.
57
- 5. Group related commits into one bullet if they tell the same story.
58
- 6. Be specific — avoid vague phrases like "improved performance" without a number or context.
59
- 7. Keep each bullet to 1–2 sentences.
60
-
61
- Respond with ONLY valid JSON matching this schema exactly:
62
- {
63
- "items": [
64
- {
65
- "status": "done" | "in_progress",
66
- "summary": "Plain English summary of what was accomplished",
67
- "impact": "Why this matters — business value, who it unblocks, what risk it reduces. Omit if unknown.",
68
- "technical_note": "Optional: brief technical aside for a technical reader (1 phrase max)"
69
- }
70
- ],
71
- "files_summary": "Brief description of what areas of the codebase were touched (e.g. 'auth module + database layer')",
72
- "total_commits": ${git.commits.length},
73
- "total_files": ${git.totalFilesChanged}
74
- }
75
-
76
- If there are no commits and no GitHub activity, return:
77
- {"items": [], "files_summary": "", "total_commits": 0, "total_files": 0}
78
- `;
79
- }
80
- function buildReviewPrompt(entries, context, periodLabel) {
81
- const contextBlock = context?.companyDescription
82
- ? `Company: ${context.companyDescription}\nManager priorities: ${context.managerPriorities ?? "not specified"}`
83
- : "";
84
- const entriesBlock = entries
85
- .map((e) => `### ${e.date} (${e.repoName}, ${e.totalCommits} commits)\n${e.items.map((i) => `- [${i.status}] ${i.summary}. ${i.impact}`).join("\n")}`)
86
- .join("\n\n");
87
- return `You are writing a professional performance review summary for a software engineer.
88
-
89
- ${contextBlock}
90
-
91
- ## Work Log — ${periodLabel}
92
-
93
- ${entriesBlock}
94
-
95
- ## Your Task
96
- Synthesize the above daily work logs into a structured performance review summary. Group by theme (e.g. "Features shipped", "Reliability & bugs", "Security", "Code review", "Infrastructure").
97
-
98
- Respond with ONLY valid JSON:
99
- {
100
- "period": "${periodLabel}",
101
- "themes": [
102
- {
103
- "name": "Theme name",
104
- "bullets": ["Specific achievement...", "..."],
105
- "impact_level": "high" | "medium" | "low"
106
- }
107
- ],
108
- "stats": {
109
- "total_commits": number,
110
- "working_days": number,
111
- "prs_reviewed": number
112
- },
113
- "headline": "One sentence that captures the engineer's biggest contribution this period"
114
- }
115
- `;
116
- }
117
- //# sourceMappingURL=prompt.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/translator/prompt.ts"],"names":[],"mappings":"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"}
@@ -1,36 +0,0 @@
1
- import { GitSummary } from "../readers/git";
2
- import { GitHubSummary } from "../readers/github";
3
- import { UserContext, ImpactItem } from "../storage/db";
4
- export interface TranslationResult {
5
- items: ImpactItem[];
6
- filesSummary: string;
7
- totalCommits: number;
8
- totalFiles: number;
9
- rawJson: string;
10
- }
11
- export interface ReviewResult {
12
- period: string;
13
- themes: Array<{
14
- name: string;
15
- bullets: string[];
16
- impact_level: "high" | "medium" | "low";
17
- }>;
18
- stats: {
19
- total_commits: number;
20
- working_days: number;
21
- prs_reviewed: number;
22
- };
23
- headline: string;
24
- }
25
- export declare function translateActivity(git: GitSummary, github: GitHubSummary | null, context: UserContext | null, dateLabel: string): Promise<TranslationResult>;
26
- export declare function generateReview(entries: Array<{
27
- date: string;
28
- items: Array<{
29
- status: string;
30
- summary: string;
31
- impact: string;
32
- }>;
33
- totalCommits: number;
34
- repoName: string;
35
- }>, context: UserContext | null, periodLabel: string): Promise<ReviewResult>;
36
- //# sourceMappingURL=translate.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"translate.d.ts","sourceRoot":"","sources":["../../src/translator/translate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGxD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,YAAY,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;KACzC,CAAC,CAAC;IACH,KAAK,EAAE;QACL,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,QAAQ,EAAE,MAAM,CAAC;CAClB;AAYD,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,UAAU,EACf,MAAM,EAAE,aAAa,GAAG,IAAI,EAC5B,OAAO,EAAE,WAAW,GAAG,IAAI,EAC3B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,iBAAiB,CAAC,CAmD5B;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,KAAK,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClE,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,EACF,OAAO,EAAE,WAAW,GAAG,IAAI,EAC3B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,YAAY,CAAC,CAoBvB"}
@@ -1,73 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.translateActivity = translateActivity;
7
- exports.generateReview = generateReview;
8
- const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
9
- const prompt_1 = require("./prompt");
10
- function getAnthropicKey(context) {
11
- const key = context?.anthropicApiKey || process.env.ANTHROPIC_API_KEY;
12
- if (!key) {
13
- throw new Error("No Anthropic API key found. Run `git-impact init` to set one, or set ANTHROPIC_API_KEY env var.");
14
- }
15
- return key;
16
- }
17
- async function translateActivity(git, github, context, dateLabel) {
18
- const client = new sdk_1.default({ apiKey: getAnthropicKey(context) });
19
- const input = { git, github, context, dateLabel };
20
- const prompt = (0, prompt_1.buildPrompt)(input);
21
- if (git.commits.length === 0 && !github) {
22
- return {
23
- items: [],
24
- filesSummary: "",
25
- totalCommits: 0,
26
- totalFiles: 0,
27
- rawJson: "{}",
28
- };
29
- }
30
- const message = await client.messages.create({
31
- model: "claude-sonnet-4-6",
32
- max_tokens: 1024,
33
- system: "You are a concise technical writer. Always respond with valid JSON only. No markdown, no explanation outside the JSON object.",
34
- messages: [{ role: "user", content: prompt }],
35
- });
36
- const text = message.content
37
- .filter((b) => b.type === "text")
38
- .map((b) => b.text)
39
- .join("");
40
- let parsed;
41
- try {
42
- // strip possible markdown code fences
43
- const clean = text.replace(/^```(?:json)?\s*/m, "").replace(/\s*```$/m, "").trim();
44
- parsed = JSON.parse(clean);
45
- }
46
- catch {
47
- throw new Error(`Claude returned invalid JSON:\n${text}`);
48
- }
49
- return {
50
- items: parsed.items ?? [],
51
- filesSummary: parsed.files_summary ?? "",
52
- totalCommits: parsed.total_commits ?? git.commits.length,
53
- totalFiles: parsed.total_files ?? git.totalFilesChanged,
54
- rawJson: text,
55
- };
56
- }
57
- async function generateReview(entries, context, periodLabel) {
58
- const client = new sdk_1.default({ apiKey: getAnthropicKey(context) });
59
- const prompt = (0, prompt_1.buildReviewPrompt)(entries, context, periodLabel);
60
- const message = await client.messages.create({
61
- model: "claude-sonnet-4-6",
62
- max_tokens: 2048,
63
- system: "You are a professional technical writer. Always respond with valid JSON only. No markdown outside the JSON.",
64
- messages: [{ role: "user", content: prompt }],
65
- });
66
- const text = message.content
67
- .filter((b) => b.type === "text")
68
- .map((b) => b.text)
69
- .join("");
70
- const clean = text.replace(/^```(?:json)?\s*/m, "").replace(/\s*```$/m, "").trim();
71
- return JSON.parse(clean);
72
- }
73
- //# sourceMappingURL=translate.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/translator/translate.ts"],"names":[],"mappings":";;;;;AAuCA,8CAwDC;AAED,wCA6BC;AA9HD,4DAA0C;AAI1C,qCAA0E;AAyB1E,SAAS,eAAe,CAAC,OAA2B;IAClD,MAAM,GAAG,GAAG,OAAO,EAAE,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IACtE,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CACb,iGAAiG,CAClG,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAEM,KAAK,UAAU,iBAAiB,CACrC,GAAe,EACf,MAA4B,EAC5B,OAA2B,EAC3B,SAAiB;IAEjB,MAAM,MAAM,GAAG,IAAI,aAAS,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAEnE,MAAM,KAAK,GAAmB,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;IAClE,MAAM,MAAM,GAAG,IAAA,oBAAW,EAAC,KAAK,CAAC,CAAC;IAElC,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACxC,OAAO;YACL,KAAK,EAAE,EAAE;YACT,YAAY,EAAE,EAAE;YAChB,YAAY,EAAE,CAAC;YACf,UAAU,EAAE,CAAC;YACb,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC3C,KAAK,EAAE,mBAAmB;QAC1B,UAAU,EAAE,IAAI;QAChB,MAAM,EACJ,+HAA+H;QACjI,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;KAC9C,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO;SACzB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;SAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAE,CAAoC,CAAC,IAAI,CAAC;SACtD,IAAI,CAAC,EAAE,CAAC,CAAC;IAEZ,IAAI,MAKH,CAAC;IAEF,IAAI,CAAC;QACH,sCAAsC;QACtC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACnF,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,kCAAkC,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE;QACzB,YAAY,EAAE,MAAM,CAAC,aAAa,IAAI,EAAE;QACxC,YAAY,EAAE,MAAM,CAAC,aAAa,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM;QACxD,UAAU,EAAE,MAAM,CAAC,WAAW,IAAI,GAAG,CAAC,iBAAiB;QACvD,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,cAAc,CAClC,OAKE,EACF,OAA2B,EAC3B,WAAmB;IAEnB,MAAM,MAAM,GAAG,IAAI,aAAS,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAEnE,MAAM,MAAM,GAAG,IAAA,0BAAiB,EAAC,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;IAEhE,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC3C,KAAK,EAAE,mBAAmB;QAC1B,UAAU,EAAE,IAAI;QAChB,MAAM,EACJ,6GAA6G;QAC/G,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;KAC9C,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO;SACzB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;SAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAE,CAAoC,CAAC,IAAI,CAAC;SACtD,IAAI,CAAC,EAAE,CAAC,CAAC;IAEZ,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACnF,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAiB,CAAC;AAC3C,CAAC"}