gitforest 0.1.0 → 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 (183) hide show
  1. package/LICENSE +21 -0
  2. package/package.json +24 -4
  3. package/src/github/auth.ts +3 -3
  4. package/src/utils/debug.ts +4 -4
  5. package/.bunignore +0 -7
  6. package/.github/workflows/ci.yml +0 -73
  7. package/CLAUDE.md +0 -111
  8. package/CONTRIBUTING.md +0 -145
  9. package/bun.lock +0 -267
  10. package/bunfig.toml +0 -15
  11. package/cli +0 -0
  12. package/docs/ai/IMPROVEMENT_PLAN.md +0 -341
  13. package/docs/ai/VERIFICATION_REPORT.md +0 -87
  14. package/docs/ai/architecture.md +0 -169
  15. package/docs/ai/checks/check-2025-12-02-tests.md +0 -40
  16. package/docs/ai/checks/check-2025-12-02.md +0 -55
  17. package/docs/ai/checks/test-verification-report.md +0 -85
  18. package/docs/ai/implementation-guide.md +0 -776
  19. package/docs/ai/research/gitty-codebase-analysis.md +0 -221
  20. package/docs/ai/tickets/GENERAL-sitrep.md +0 -30
  21. package/docs/ai/tickets/TASK-database-tests-sitrep.md +0 -25
  22. package/docs/ai/tickets/TASK-deprecated-functions-sitrep.md +0 -28
  23. package/docs/ai/tickets/TASK-detail-modal-sitrep.md +0 -28
  24. package/docs/ai/tickets/TASK-filter-overlay-sitrep.md +0 -24
  25. package/docs/ai/tickets/TASK-github-service-sitrep.md +0 -32
  26. package/docs/ai/tickets/TASK-github-token-sitrep.md +0 -51
  27. package/docs/ai/tickets/TASK-hascommits-sitrep.md +0 -35
  28. package/docs/ai/tickets/TASK-keybindings-sitrep.md +0 -26
  29. package/docs/ai/tickets/TASK-layout-sitrep.md +0 -25
  30. package/docs/ai/tickets/TASK-markdown-sitrep.md +0 -28
  31. package/docs/ai/tickets/TASK-project-item-sitrep.md +0 -79
  32. package/docs/ai/tickets/TASK-sitrep.md +0 -28
  33. package/docs/ai/tickets/TASK-state-sitrep.md +0 -26
  34. package/docs/ai/tickets/TASK-types-sitrep.md +0 -25
  35. package/docs/ai/tickets/TASK-unified-item-fix-sitrep.md +0 -26
  36. package/docs/ai/tickets/TKT-001-sitrep.md +0 -24
  37. package/docs/ai/tickets/TKT-002-sitrep.md +0 -25
  38. package/docs/ai/tickets/TKT-003-git-service-refactoring-complete.md +0 -46
  39. package/docs/ai/tickets/TKT-003-git-service-refactoring-plan.md +0 -135
  40. package/docs/ai/tickets/TKT-003-sitrep.md +0 -26
  41. package/docs/ai/tickets/TKT-004-sitrep.md +0 -27
  42. package/docs/ai/tickets/TKT-005-sitrep.md +0 -25
  43. package/docs/ai/tickets/TKT-006-sitrep.md +0 -26
  44. package/docs/ai/tickets/TKT-007-sitrep.md +0 -30
  45. package/docs/ai/tickets/TKT-008-sitrep.md +0 -32
  46. package/docs/ai/tickets/TKT-009-sitrep.md +0 -27
  47. package/docs/ai/tickets/TKT-010-sitrep.md +0 -27
  48. package/docs/ai/tickets/TKT-011-sitrep.md +0 -26
  49. package/docs/ai/tickets/TKT-012-sitrep.md +0 -25
  50. package/docs/ai/tickets/sitreps/TASK-actions-sitrep.md +0 -28
  51. package/docs/ai/tickets/sitreps/TASK-actions-test-sitrep.md +0 -25
  52. package/docs/ai/tickets/sitreps/TASK-app-integration-sitrep.md +0 -25
  53. package/docs/ai/tickets/sitreps/TASK-background-fetch-sitrep.md +0 -24
  54. package/docs/ai/tickets/sitreps/TASK-background-fetch-test-sitrep.md +0 -29
  55. package/docs/ai/tickets/sitreps/TASK-batch-tests-sitrep.md +0 -29
  56. package/docs/ai/tickets/sitreps/TASK-bun-test-sitrep.md +0 -26
  57. package/docs/ai/tickets/sitreps/TASK-cache-tests-sitrep.md +0 -30
  58. package/docs/ai/tickets/sitreps/TASK-cli-tests-sitrep.md +0 -28
  59. package/docs/ai/tickets/sitreps/TASK-clone-error-handling-sitrep.md +0 -26
  60. package/docs/ai/tickets/sitreps/TASK-commands-tests-sitrep.md +0 -25
  61. package/docs/ai/tickets/sitreps/TASK-component-tests-1-sitrep.md +0 -30
  62. package/docs/ai/tickets/sitreps/TASK-configloader-tests-sitrep.md +0 -25
  63. package/docs/ai/tickets/sitreps/TASK-confirm-dialog-test-sitrep.md +0 -29
  64. package/docs/ai/tickets/sitreps/TASK-coverage-sitrep.md +0 -95
  65. package/docs/ai/tickets/sitreps/TASK-database-tests-summary.md +0 -61
  66. package/docs/ai/tickets/sitreps/TASK-error-boundary-sitrep.md +0 -30
  67. package/docs/ai/tickets/sitreps/TASK-error-tests-sitrep.md +0 -27
  68. package/docs/ai/tickets/sitreps/TASK-errors-tests-sitrep.md +0 -25
  69. package/docs/ai/tickets/sitreps/TASK-extract-reducer-sitrep.md +0 -27
  70. package/docs/ai/tickets/sitreps/TASK-filter-overlay-test-sitrep.md +0 -25
  71. package/docs/ai/tickets/sitreps/TASK-final-verification-sitrep.md +0 -28
  72. package/docs/ai/tickets/sitreps/TASK-fix-all-tests-sitrep.md +0 -25
  73. package/docs/ai/tickets/sitreps/TASK-fix-hooks-sitrep.md +0 -26
  74. package/docs/ai/tickets/sitreps/TASK-fix-remaining-tests-sitrep.md +0 -25
  75. package/docs/ai/tickets/sitreps/TASK-fix-test-failures-sitrep.md +0 -26
  76. package/docs/ai/tickets/sitreps/TASK-fix-tests-sitrep.md +0 -24
  77. package/docs/ai/tickets/sitreps/TASK-formatters-tests-sitrep.md +0 -25
  78. package/docs/ai/tickets/sitreps/TASK-git-timeouts-sitrep.md +0 -29
  79. package/docs/ai/tickets/sitreps/TASK-github-cache-test-sitrep.md +0 -25
  80. package/docs/ai/tickets/sitreps/TASK-githubcli-tests-sitrep.md +0 -24
  81. package/docs/ai/tickets/sitreps/TASK-gitstatus-tests-sitrep.md +0 -24
  82. package/docs/ai/tickets/sitreps/TASK-hooks-isolation-sitrep.md +0 -27
  83. package/docs/ai/tickets/sitreps/TASK-keybindings-tests-sitrep.md +0 -25
  84. package/docs/ai/tickets/sitreps/TASK-layout-tests-sitrep.md +0 -25
  85. package/docs/ai/tickets/sitreps/TASK-mock-factories-sitrep.md +0 -27
  86. package/docs/ai/tickets/sitreps/TASK-modal-tests-sitrep.md +0 -32
  87. package/docs/ai/tickets/sitreps/TASK-processbatch-fix-sitrep.md +0 -27
  88. package/docs/ai/tickets/sitreps/TASK-projectlist-tests-sitrep.md +0 -30
  89. package/docs/ai/tickets/sitreps/TASK-projectutils-tests-sitrep.md +0 -25
  90. package/docs/ai/tickets/sitreps/TASK-scanner-tests-sitrep.md +0 -29
  91. package/docs/ai/tickets/sitreps/TASK-select-all-sitrep.md +0 -25
  92. package/docs/ai/tickets/sitreps/TASK-shell-error-handling-sitrep.md +0 -27
  93. package/docs/ai/tickets/sitreps/TASK-store-tests-sitrep.md +0 -25
  94. package/docs/ai/tickets/sitreps/TASK-test-fixes-sitrep.md +0 -26
  95. package/docs/ai/tickets/sitreps/TASK-test-summary-sitrep.md +0 -25
  96. package/docs/ai/tickets/sitreps/TASK-test-verification-sitrep.md +0 -27
  97. package/docs/ai/tickets/sitreps/TASK-testsuite-sitrep.md +0 -75
  98. package/docs/ai/tickets/sitreps/TASK-unified-reducer-tests-sitrep.md +0 -29
  99. package/docs/ai/tickets/sitreps/TASK-unified-repos-test-sitrep.md +0 -29
  100. package/docs/ai/tickets/sitreps/TASK-unified-tests-sitrep.md +0 -25
  101. package/docs/ai/tickets/sitreps/TASK-useprojects-tests-sitrep.md +0 -25
  102. package/docs/ai/tickets/sitreps/TASK-utility-tests-sitrep.md +0 -32
  103. package/docs/ai/tickets/sitreps/TKT-003-git-service-refactoring-sitrep.md +0 -64
  104. package/docs/ai/tkt-001-fix-database-error.md +0 -217
  105. package/docs/ai/ui-enhancement-plan.md +0 -562
  106. package/test/integration/app.isolated.tsx +0 -240
  107. package/test/integration/cli-commands.test.ts +0 -287
  108. package/test/integration/cli-validation.test.ts +0 -264
  109. package/test/integration/git-operations.test.ts +0 -218
  110. package/test/integration/scanner.test.ts +0 -228
  111. package/test/preload.ts +0 -18
  112. package/test/unit/cli/commands.test.ts +0 -13
  113. package/test/unit/cli/formatters.test.ts +0 -1116
  114. package/test/unit/cli/github-commands.test.ts +0 -12
  115. package/test/unit/components/CloneDialog.test.tsx +0 -240
  116. package/test/unit/components/ColumnHeader.test.tsx +0 -128
  117. package/test/unit/components/CommandPalette.test.tsx +0 -355
  118. package/test/unit/components/ConfirmDialog.test.tsx +0 -111
  119. package/test/unit/components/ErrorBoundary.test.tsx +0 -139
  120. package/test/unit/components/FilterBar.test.tsx +0 -43
  121. package/test/unit/components/FilterOptionsOverlay.test.tsx +0 -197
  122. package/test/unit/components/HelpOverlay.test.tsx +0 -90
  123. package/test/unit/components/Layout.test.tsx +0 -328
  124. package/test/unit/components/MarkdownRenderer.test.tsx +0 -45
  125. package/test/unit/components/ProgressBar.test.tsx +0 -138
  126. package/test/unit/components/ProjectItem.test.tsx +0 -182
  127. package/test/unit/components/ProjectList.test.tsx +0 -311
  128. package/test/unit/components/RepoDetailModal.test.tsx +0 -445
  129. package/test/unit/components/StatusBar.test.tsx +0 -112
  130. package/test/unit/components/UnifiedProjectItem.test.tsx +0 -618
  131. package/test/unit/components/ViewModeIndicator.test.tsx +0 -137
  132. package/test/unit/components/test-utils.tsx +0 -63
  133. package/test/unit/config/loader.test.ts +0 -692
  134. package/test/unit/db/database.test.ts +0 -978
  135. package/test/unit/db/index.test.ts +0 -314
  136. package/test/unit/fixtures/setup.ts +0 -186
  137. package/test/unit/git/commands-untested.test.ts +0 -205
  138. package/test/unit/git/commands.test.ts +0 -269
  139. package/test/unit/git/operations.test.ts +0 -322
  140. package/test/unit/git/status.test.ts +0 -219
  141. package/test/unit/github/auth.test.ts +0 -317
  142. package/test/unit/github/cache.test.ts +0 -1028
  143. package/test/unit/github/cli.test.ts +0 -135
  144. package/test/unit/github/unified.test.ts +0 -1201
  145. package/test/unit/graceful-shutdown.test.ts +0 -83
  146. package/test/unit/hooks/useBackgroundFetch.test.tsx +0 -239
  147. package/test/unit/hooks/useConfirmDialogActions.test.tsx +0 -81
  148. package/test/unit/hooks/useKeyBindings.isolated.ts +0 -715
  149. package/test/unit/hooks/useProjects.test.tsx +0 -186
  150. package/test/unit/hooks/useUnifiedRepos-simple.test.tsx +0 -115
  151. package/test/unit/hooks/useUnifiedRepos.test.tsx +0 -177
  152. package/test/unit/mocks/config.ts +0 -109
  153. package/test/unit/mocks/git-service.ts +0 -274
  154. package/test/unit/mocks/github-service.ts +0 -250
  155. package/test/unit/mocks/index.ts +0 -72
  156. package/test/unit/mocks/project.ts +0 -148
  157. package/test/unit/mocks/state-mocks.ts +0 -187
  158. package/test/unit/mocks/unified.ts +0 -169
  159. package/test/unit/operations/batch.test.ts +0 -216
  160. package/test/unit/operations/commands.test.ts +0 -550
  161. package/test/unit/scanner/errors.test.ts +0 -297
  162. package/test/unit/scanner/index.test.ts +0 -1011
  163. package/test/unit/scanner/markers.test.ts +0 -150
  164. package/test/unit/scanner/submodules.test.ts +0 -99
  165. package/test/unit/services/git-errors.test.ts +0 -190
  166. package/test/unit/services/git.test.ts +0 -442
  167. package/test/unit/services/github-errors.test.ts +0 -293
  168. package/test/unit/services/github.test.ts +0 -200
  169. package/test/unit/state/actions.test.ts +0 -217
  170. package/test/unit/state/reducer.test.ts +0 -745
  171. package/test/unit/state/store.test.tsx +0 -711
  172. package/test/unit/types/commands.test.ts +0 -220
  173. package/test/unit/types/schema.test.ts +0 -179
  174. package/test/unit/utils/array.test.ts +0 -73
  175. package/test/unit/utils/debug.test.ts +0 -23
  176. package/test/unit/utils/errors.test.ts +0 -295
  177. package/test/unit/utils/markdown.test.ts +0 -163
  178. package/test/unit/utils/project-utils.test.ts +0 -756
  179. package/test/unit/utils/rate-limiter.test.ts +0 -256
  180. package/test/unit/utils/retry.test.ts +0 -165
  181. package/test/unit/utils/strip-ansi.ts +0 -13
  182. package/test/unit/utils/timeout.test.ts +0 -93
  183. package/tsconfig.json +0 -29
@@ -1,216 +0,0 @@
1
- /**
2
- * Tests for batch operations using service mocks
3
- *
4
- * NOTE: This file must NOT have any module mocks as it tests real implementations.
5
- * We restore any mocks at the start to ensure isolation.
6
- */
7
-
8
- import { describe, test, expect, afterAll, mock } from "bun:test";
9
-
10
- // Restore any mocks from other test files before importing real modules
11
- mock.restore();
12
-
13
- import {
14
- batchPull,
15
- batchPush,
16
- batchFetch,
17
- batchRefreshStatus,
18
- } from "../../../src/operations/batch.ts";
19
- import {
20
- createMockGitService,
21
- createSpyGitService,
22
- createSuccessResult,
23
- createFailureResult,
24
- defaultMockStatus,
25
- createAheadStatus,
26
- } from "../mocks/git-service.ts";
27
- import {
28
- createMockProject,
29
- createAheadProject,
30
- createNonGitProject,
31
- } from "../mocks/project.ts";
32
-
33
- describe("batch operations", () => {
34
- describe("batchPull", () => {
35
- test("pulls projects with remotes", async () => {
36
- const { service, calls } = createSpyGitService();
37
- const projects = [
38
- createMockProject({ name: "repo-1" }),
39
- createMockProject({ name: "repo-2" }),
40
- ];
41
-
42
- const result = await batchPull(projects, { gitService: service });
43
-
44
- expect(result.total).toBe(2);
45
- expect(result.successful).toBe(2);
46
- expect(result.failed).toBe(0);
47
- expect(calls.filter((c) => c.method === "pull")).toHaveLength(2);
48
- });
49
-
50
- test("skips projects without remotes", async () => {
51
- const { service, calls } = createSpyGitService();
52
- const projects = [
53
- createMockProject({
54
- name: "with-remote",
55
- status: { ...defaultMockStatus, hasRemote: true },
56
- }),
57
- createMockProject({
58
- name: "no-remote",
59
- status: { ...defaultMockStatus, hasRemote: false },
60
- }),
61
- ];
62
-
63
- const result = await batchPull(projects, { gitService: service });
64
-
65
- expect(result.total).toBe(1); // Only one has remote
66
- expect(calls.filter((c) => c.method === "pull")).toHaveLength(1);
67
- });
68
-
69
- test("skips non-git projects", async () => {
70
- const { service, calls } = createSpyGitService();
71
- const projects = [
72
- createMockProject({ name: "git-repo" }),
73
- createNonGitProject("npm-package"),
74
- ];
75
-
76
- const result = await batchPull(projects, { gitService: service });
77
-
78
- expect(result.total).toBe(1);
79
- expect(calls.filter((c) => c.method === "pull")).toHaveLength(1);
80
- });
81
-
82
- test("handles pull failures", async () => {
83
- const service = createMockGitService({
84
- pullResult: (path) =>
85
- path.includes("fail")
86
- ? createFailureResult("pull", "Network error", path)
87
- : createSuccessResult("pull", path),
88
- });
89
-
90
- const projects = [
91
- createMockProject({ name: "success-repo", path: "/test/success-repo" }),
92
- createMockProject({ name: "fail-repo", path: "/test/fail-repo" }),
93
- ];
94
-
95
- const result = await batchPull(projects, { gitService: service });
96
-
97
- expect(result.total).toBe(2);
98
- expect(result.successful).toBe(1);
99
- expect(result.failed).toBe(1);
100
- });
101
-
102
- test("reports progress during pull", async () => {
103
- const { service } = createSpyGitService();
104
- const projects = [
105
- createMockProject({ name: "repo-1" }),
106
- createMockProject({ name: "repo-2" }),
107
- createMockProject({ name: "repo-3" }),
108
- ];
109
-
110
- const progressCalls: [number, number][] = [];
111
- await batchPull(projects, {
112
- gitService: service,
113
- concurrency: 2,
114
- onProgress: (completed, total) => {
115
- progressCalls.push([completed, total]);
116
- },
117
- });
118
-
119
- expect(progressCalls.length).toBeGreaterThan(0);
120
- // Last call should have all projects completed
121
- const lastCall = progressCalls[progressCalls.length - 1]!;
122
- expect(lastCall[0]).toBe(3); // completed
123
- expect(lastCall[1]).toBe(3); // total
124
- });
125
- });
126
-
127
- describe("batchPush", () => {
128
- test("pushes projects that are ahead", async () => {
129
- const { service, calls } = createSpyGitService();
130
- const projects = [
131
- createAheadProject("ahead-repo", 3),
132
- createMockProject({ name: "clean-repo" }), // Not ahead
133
- ];
134
-
135
- const result = await batchPush(projects, { gitService: service });
136
-
137
- expect(result.total).toBe(1); // Only one is ahead
138
- expect(result.successful).toBe(1);
139
- expect(calls.filter((c) => c.method === "push")).toHaveLength(1);
140
- });
141
-
142
- test("skips projects without remotes even if ahead status", async () => {
143
- const { service, calls } = createSpyGitService();
144
- const projects = [
145
- createMockProject({
146
- name: "ahead-no-remote",
147
- status: {
148
- ...createAheadStatus(3),
149
- hasRemote: false,
150
- },
151
- }),
152
- ];
153
-
154
- const result = await batchPush(projects, { gitService: service });
155
-
156
- expect(result.total).toBe(0);
157
- expect(calls.filter((c) => c.method === "push")).toHaveLength(0);
158
- });
159
- });
160
-
161
- describe("batchFetch", () => {
162
- test("fetches all projects with remotes", async () => {
163
- const { service, calls } = createSpyGitService();
164
- const projects = [
165
- createMockProject({ name: "repo-1" }),
166
- createMockProject({ name: "repo-2" }),
167
- ];
168
-
169
- const result = await batchFetch(projects, { gitService: service });
170
-
171
- expect(result.total).toBe(2);
172
- expect(result.successful).toBe(2);
173
- expect(calls.filter((c) => c.method === "fetchAll")).toHaveLength(2);
174
- });
175
- });
176
-
177
- describe("batchRefreshStatus", () => {
178
- test("refreshes status for git projects", async () => {
179
- const { service, calls } = createSpyGitService();
180
- const projects = [
181
- createMockProject({ name: "repo-1", id: "id-1" }),
182
- createMockProject({ name: "repo-2", id: "id-2" }),
183
- createNonGitProject("npm-package"),
184
- ];
185
-
186
- const results = await batchRefreshStatus(projects, { gitService: service });
187
-
188
- // Should have refreshed 2 git projects
189
- expect(results.size).toBe(2);
190
- expect(results.has("id-1")).toBe(true);
191
- expect(results.has("id-2")).toBe(true);
192
- expect(calls.filter((c) => c.method === "getStatus")).toHaveLength(2);
193
- });
194
-
195
- test("preserves project data on status refresh", async () => {
196
- const { service } = createSpyGitService();
197
- const project = createMockProject({
198
- name: "my-repo",
199
- id: "my-id",
200
- path: "/test/my-repo",
201
- });
202
-
203
- const results = await batchRefreshStatus([project], { gitService: service });
204
-
205
- const refreshed = results.get("my-id")!;
206
- expect(refreshed.name).toBe("my-repo");
207
- expect(refreshed.path).toBe("/test/my-repo");
208
- expect(refreshed.lastScanned).toBeDefined();
209
- });
210
- });
211
- });
212
-
213
- // Restore all mocks after all tests complete
214
- afterAll(() => {
215
- mock.restore();
216
- });