codewalk 0.1.0 → 0.1.2

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.
package/dist/utils/git.js DELETED
@@ -1,132 +0,0 @@
1
- import { execSync } from 'child_process';
2
- export function getCurrentBranch(cwd) {
3
- try {
4
- return execSync('git rev-parse --abbrev-ref HEAD', {
5
- cwd,
6
- encoding: 'utf-8',
7
- }).trim();
8
- }
9
- catch {
10
- throw new Error('Not a git repository or git is not installed');
11
- }
12
- }
13
- export function getCommitList(cwd) {
14
- try {
15
- const output = execSync('git log --format="%H|%h|%an|%s" --first-parent', {
16
- cwd,
17
- encoding: 'utf-8',
18
- });
19
- return output
20
- .trim()
21
- .split('\n')
22
- .filter(Boolean)
23
- .map((line) => {
24
- const [sha, shortSha, author, ...messageParts] = line.split('|');
25
- return {
26
- sha,
27
- shortSha,
28
- author,
29
- message: messageParts.join('|'),
30
- };
31
- });
32
- }
33
- catch {
34
- throw new Error('Failed to get commit list');
35
- }
36
- }
37
- export function isGitRepo(cwd) {
38
- try {
39
- execSync('git rev-parse --git-dir', { cwd, encoding: 'utf-8' });
40
- return true;
41
- }
42
- catch {
43
- return false;
44
- }
45
- }
46
- export function getMainBranch(cwd) {
47
- try {
48
- // Try to get the default branch from origin
49
- const result = execSync('git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null || echo "refs/heads/main"', {
50
- cwd,
51
- encoding: 'utf-8',
52
- }).trim();
53
- return result.replace('refs/remotes/origin/', '').replace('refs/heads/', '');
54
- }
55
- catch {
56
- return 'main';
57
- }
58
- }
59
- export function getMergeBase(cwd, branch1, branch2) {
60
- try {
61
- return execSync(`git merge-base ${branch1} ${branch2}`, {
62
- cwd,
63
- encoding: 'utf-8',
64
- }).trim();
65
- }
66
- catch {
67
- throw new Error(`Failed to find merge base between ${branch1} and ${branch2}`);
68
- }
69
- }
70
- export function getCommitDiff(cwd, commitSha) {
71
- try {
72
- return execSync(`git show ${commitSha} --format="" --patch`, {
73
- cwd,
74
- encoding: 'utf-8',
75
- maxBuffer: 10 * 1024 * 1024, // 10MB buffer for large diffs
76
- });
77
- }
78
- catch {
79
- return '';
80
- }
81
- }
82
- export function parseDiffIntoFiles(diffOutput) {
83
- const files = [];
84
- // Split by file headers (diff --git a/... b/...)
85
- const fileChunks = diffOutput.split(/^diff --git /m).filter(Boolean);
86
- for (const chunk of fileChunks) {
87
- const lines = chunk.split('\n');
88
- // Extract file path from the first line (a/path b/path)
89
- const headerMatch = lines[0]?.match(/a\/(.+?) b\/(.+)/);
90
- if (!headerMatch)
91
- continue;
92
- const filePath = headerMatch[2];
93
- const hunks = [];
94
- let currentHunk = null;
95
- let hunkNumber = 0;
96
- for (let i = 1; i < lines.length; i++) {
97
- const line = lines[i];
98
- // Start of a new hunk
99
- if (line.startsWith('@@')) {
100
- if (currentHunk) {
101
- hunks.push(currentHunk);
102
- }
103
- hunkNumber++;
104
- currentHunk = {
105
- hunkNumber,
106
- header: line,
107
- content: '',
108
- };
109
- }
110
- else if (currentHunk) {
111
- // Skip binary file markers and other metadata
112
- if (line.startsWith('Binary files') || line.startsWith('index ') ||
113
- line.startsWith('---') || line.startsWith('+++') ||
114
- line.startsWith('new file') || line.startsWith('deleted file')) {
115
- continue;
116
- }
117
- currentHunk.content += line + '\n';
118
- }
119
- }
120
- if (currentHunk) {
121
- hunks.push(currentHunk);
122
- }
123
- if (hunks.length > 0) {
124
- files.push({ path: filePath, hunks });
125
- }
126
- }
127
- return files;
128
- }
129
- export function getCommitFileDiffs(cwd, commitSha) {
130
- const diffOutput = getCommitDiff(cwd, commitSha);
131
- return parseDiffIntoFiles(diffOutput);
132
- }
@@ -1,23 +0,0 @@
1
- import type { Changeset } from '../types/codewalker.js';
2
- import type { CommitInfo, ParsedHunk } from './git.js';
3
- export interface TrackedCommit {
4
- commit: CommitInfo;
5
- tracking: Changeset | null;
6
- }
7
- export interface FileWithHunks {
8
- path: string;
9
- hunks: ParsedHunk[];
10
- hunkNumbers: number[];
11
- }
12
- export interface ReasoningGroup {
13
- reasoning: string;
14
- files: FileWithHunks[];
15
- }
16
- export declare function loadTrackingFiles(cwd: string, commits: CommitInfo[]): Promise<TrackedCommit[]>;
17
- export declare function getTrackedCommits(trackedCommits: TrackedCommit[]): TrackedCommit[];
18
- /**
19
- * Aggregates all tracking data into reasoning groups with actual diff hunks.
20
- * This is the "By Reasoning" view - grouping changes by their logical purpose.
21
- */
22
- export declare function aggregateByReasoning(cwd: string, trackedCommits: TrackedCommit[]): ReasoningGroup[];
23
- //# sourceMappingURL=tracking.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tracking.d.ts","sourceRoot":"","sources":["../../src/utils/tracking.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAY,UAAU,EAAE,MAAM,UAAU,CAAC;AAGjE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,SAAS,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AAED,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,UAAU,EAAE,GACpB,OAAO,CAAC,aAAa,EAAE,CAAC,CAkB1B;AAED,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,aAAa,EAAE,GAAG,aAAa,EAAE,CAElF;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,cAAc,EAAE,aAAa,EAAE,GAC9B,cAAc,EAAE,CAiElB"}
@@ -1,85 +0,0 @@
1
- import * as fs from 'fs/promises';
2
- import * as path from 'path';
3
- import { getCommitFileDiffs } from './git.js';
4
- export async function loadTrackingFiles(cwd, commits) {
5
- const result = [];
6
- for (const commit of commits) {
7
- const trackingPath = path.join(cwd, '.codewalker', `${commit.shortSha}.json`);
8
- let tracking = null;
9
- try {
10
- const content = await fs.readFile(trackingPath, 'utf-8');
11
- tracking = JSON.parse(content);
12
- }
13
- catch {
14
- // No tracking file for this commit
15
- }
16
- result.push({ commit, tracking });
17
- }
18
- return result;
19
- }
20
- export function getTrackedCommits(trackedCommits) {
21
- return trackedCommits.filter((tc) => tc.tracking !== null);
22
- }
23
- /**
24
- * Aggregates all tracking data into reasoning groups with actual diff hunks.
25
- * This is the "By Reasoning" view - grouping changes by their logical purpose.
26
- */
27
- export function aggregateByReasoning(cwd, trackedCommits) {
28
- const reasoningMap = new Map();
29
- // Build a map of commit SHA to file diffs for quick lookup
30
- const commitDiffs = new Map();
31
- for (const tc of trackedCommits) {
32
- if (!tc.tracking)
33
- continue;
34
- // Get diffs for this commit (lazy load)
35
- if (!commitDiffs.has(tc.commit.shortSha)) {
36
- commitDiffs.set(tc.commit.shortSha, getCommitFileDiffs(cwd, tc.commit.shortSha));
37
- }
38
- const fileDiffs = commitDiffs.get(tc.commit.shortSha) || [];
39
- for (const change of tc.tracking.changes) {
40
- // Use reasoning as the key (could also include commit if you want per-commit grouping)
41
- const key = change.reasoning;
42
- if (!reasoningMap.has(key)) {
43
- reasoningMap.set(key, {
44
- reasoning: change.reasoning,
45
- files: [],
46
- });
47
- }
48
- const group = reasoningMap.get(key);
49
- for (const fileChange of change.files) {
50
- // Find the diff for this file
51
- const fileDiff = fileDiffs.find((fd) => fd.path === fileChange.path);
52
- if (!fileDiff)
53
- continue;
54
- // Get only the hunks specified in the tracking file
55
- const selectedHunks = fileChange.hunks
56
- .map((hunkNum) => fileDiff.hunks.find((h) => h.hunkNumber === hunkNum))
57
- .filter((h) => h != null);
58
- if (selectedHunks.length === 0)
59
- continue;
60
- // Check if this file is already in the group
61
- const existingFile = group.files.find((f) => f.path === fileChange.path);
62
- if (existingFile) {
63
- // Merge hunks (avoid duplicates)
64
- for (const hunk of selectedHunks) {
65
- if (!existingFile.hunks.find((h) => h.hunkNumber === hunk.hunkNumber)) {
66
- existingFile.hunks.push(hunk);
67
- existingFile.hunkNumbers.push(hunk.hunkNumber);
68
- }
69
- }
70
- }
71
- else {
72
- group.files.push({
73
- path: fileChange.path,
74
- hunks: selectedHunks,
75
- hunkNumbers: fileChange.hunks,
76
- });
77
- }
78
- }
79
- }
80
- }
81
- // Convert map to array and sort by number of files (most impactful first)
82
- return Array.from(reasoningMap.values())
83
- .filter((group) => group.files.length > 0)
84
- .sort((a, b) => b.files.length - a.files.length);
85
- }