argustack 0.1.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 (219) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +433 -0
  3. package/dist/adapters/csv/index.d.ts +4 -0
  4. package/dist/adapters/csv/index.d.ts.map +1 -0
  5. package/dist/adapters/csv/index.js +4 -0
  6. package/dist/adapters/csv/index.js.map +1 -0
  7. package/dist/adapters/csv/mapper.d.ts +10 -0
  8. package/dist/adapters/csv/mapper.d.ts.map +1 -0
  9. package/dist/adapters/csv/mapper.js +179 -0
  10. package/dist/adapters/csv/mapper.js.map +1 -0
  11. package/dist/adapters/csv/parser.d.ts +22 -0
  12. package/dist/adapters/csv/parser.d.ts.map +1 -0
  13. package/dist/adapters/csv/parser.js +96 -0
  14. package/dist/adapters/csv/parser.js.map +1 -0
  15. package/dist/adapters/csv/provider.d.ts +11 -0
  16. package/dist/adapters/csv/provider.d.ts.map +1 -0
  17. package/dist/adapters/csv/provider.js +98 -0
  18. package/dist/adapters/csv/provider.js.map +1 -0
  19. package/dist/adapters/git/index.d.ts +3 -0
  20. package/dist/adapters/git/index.d.ts.map +1 -0
  21. package/dist/adapters/git/index.js +3 -0
  22. package/dist/adapters/git/index.js.map +1 -0
  23. package/dist/adapters/git/mapper.d.ts +11 -0
  24. package/dist/adapters/git/mapper.d.ts.map +1 -0
  25. package/dist/adapters/git/mapper.js +47 -0
  26. package/dist/adapters/git/mapper.js.map +1 -0
  27. package/dist/adapters/git/provider.d.ts +12 -0
  28. package/dist/adapters/git/provider.d.ts.map +1 -0
  29. package/dist/adapters/git/provider.js +115 -0
  30. package/dist/adapters/git/provider.js.map +1 -0
  31. package/dist/adapters/github/client.d.ts +8 -0
  32. package/dist/adapters/github/client.d.ts.map +1 -0
  33. package/dist/adapters/github/client.js +5 -0
  34. package/dist/adapters/github/client.js.map +1 -0
  35. package/dist/adapters/github/index.d.ts +4 -0
  36. package/dist/adapters/github/index.d.ts.map +1 -0
  37. package/dist/adapters/github/index.js +4 -0
  38. package/dist/adapters/github/index.js.map +1 -0
  39. package/dist/adapters/github/mapper.d.ts +12 -0
  40. package/dist/adapters/github/mapper.d.ts.map +1 -0
  41. package/dist/adapters/github/mapper.js +117 -0
  42. package/dist/adapters/github/mapper.js.map +1 -0
  43. package/dist/adapters/github/provider.d.ts +18 -0
  44. package/dist/adapters/github/provider.d.ts.map +1 -0
  45. package/dist/adapters/github/provider.js +95 -0
  46. package/dist/adapters/github/provider.js.map +1 -0
  47. package/dist/adapters/jira/client.d.ts +11 -0
  48. package/dist/adapters/jira/client.d.ts.map +1 -0
  49. package/dist/adapters/jira/client.js +16 -0
  50. package/dist/adapters/jira/client.js.map +1 -0
  51. package/dist/adapters/jira/index.d.ts +3 -0
  52. package/dist/adapters/jira/index.d.ts.map +1 -0
  53. package/dist/adapters/jira/index.js +3 -0
  54. package/dist/adapters/jira/index.js.map +1 -0
  55. package/dist/adapters/jira/mapper.d.ts +14 -0
  56. package/dist/adapters/jira/mapper.d.ts.map +1 -0
  57. package/dist/adapters/jira/mapper.js +169 -0
  58. package/dist/adapters/jira/mapper.js.map +1 -0
  59. package/dist/adapters/jira/provider.d.ts +21 -0
  60. package/dist/adapters/jira/provider.d.ts.map +1 -0
  61. package/dist/adapters/jira/provider.js +79 -0
  62. package/dist/adapters/jira/provider.js.map +1 -0
  63. package/dist/adapters/openai/embedding-provider.d.ts +16 -0
  64. package/dist/adapters/openai/embedding-provider.d.ts.map +1 -0
  65. package/dist/adapters/openai/embedding-provider.js +34 -0
  66. package/dist/adapters/openai/embedding-provider.js.map +1 -0
  67. package/dist/adapters/openai/index.d.ts +2 -0
  68. package/dist/adapters/openai/index.d.ts.map +1 -0
  69. package/dist/adapters/openai/index.js +2 -0
  70. package/dist/adapters/openai/index.js.map +1 -0
  71. package/dist/adapters/postgres/connection.d.ts +13 -0
  72. package/dist/adapters/postgres/connection.d.ts.map +1 -0
  73. package/dist/adapters/postgres/connection.js +16 -0
  74. package/dist/adapters/postgres/connection.js.map +1 -0
  75. package/dist/adapters/postgres/index.d.ts +3 -0
  76. package/dist/adapters/postgres/index.d.ts.map +1 -0
  77. package/dist/adapters/postgres/index.js +3 -0
  78. package/dist/adapters/postgres/index.js.map +1 -0
  79. package/dist/adapters/postgres/schema.d.ts +6 -0
  80. package/dist/adapters/postgres/schema.d.ts.map +1 -0
  81. package/dist/adapters/postgres/schema.js +246 -0
  82. package/dist/adapters/postgres/schema.js.map +1 -0
  83. package/dist/adapters/postgres/storage.d.ts +32 -0
  84. package/dist/adapters/postgres/storage.d.ts.map +1 -0
  85. package/dist/adapters/postgres/storage.js +322 -0
  86. package/dist/adapters/postgres/storage.js.map +1 -0
  87. package/dist/cli/embed.d.ts +3 -0
  88. package/dist/cli/embed.d.ts.map +1 -0
  89. package/dist/cli/embed.js +52 -0
  90. package/dist/cli/embed.js.map +1 -0
  91. package/dist/cli/index.d.ts +3 -0
  92. package/dist/cli/index.d.ts.map +1 -0
  93. package/dist/cli/index.js +64 -0
  94. package/dist/cli/index.js.map +1 -0
  95. package/dist/cli/init.d.ts +24 -0
  96. package/dist/cli/init.d.ts.map +1 -0
  97. package/dist/cli/init.js +966 -0
  98. package/dist/cli/init.js.map +1 -0
  99. package/dist/cli/jira.d.ts +3 -0
  100. package/dist/cli/jira.d.ts.map +1 -0
  101. package/dist/cli/jira.js +78 -0
  102. package/dist/cli/jira.js.map +1 -0
  103. package/dist/cli/mcp-install.d.ts +10 -0
  104. package/dist/cli/mcp-install.d.ts.map +1 -0
  105. package/dist/cli/mcp-install.js +207 -0
  106. package/dist/cli/mcp-install.js.map +1 -0
  107. package/dist/cli/sources.d.ts +10 -0
  108. package/dist/cli/sources.d.ts.map +1 -0
  109. package/dist/cli/sources.js +132 -0
  110. package/dist/cli/sources.js.map +1 -0
  111. package/dist/cli/status.d.ts +6 -0
  112. package/dist/cli/status.d.ts.map +1 -0
  113. package/dist/cli/status.js +93 -0
  114. package/dist/cli/status.js.map +1 -0
  115. package/dist/cli/sync.d.ts +21 -0
  116. package/dist/cli/sync.d.ts.map +1 -0
  117. package/dist/cli/sync.js +321 -0
  118. package/dist/cli/sync.js.map +1 -0
  119. package/dist/core/ports/embedding-provider.d.ts +15 -0
  120. package/dist/core/ports/embedding-provider.d.ts.map +1 -0
  121. package/dist/core/ports/embedding-provider.js +2 -0
  122. package/dist/core/ports/embedding-provider.js.map +1 -0
  123. package/dist/core/ports/git-provider.d.ts +30 -0
  124. package/dist/core/ports/git-provider.d.ts.map +1 -0
  125. package/dist/core/ports/git-provider.js +2 -0
  126. package/dist/core/ports/git-provider.js.map +1 -0
  127. package/dist/core/ports/github-provider.d.ts +30 -0
  128. package/dist/core/ports/github-provider.d.ts.map +1 -0
  129. package/dist/core/ports/github-provider.js +2 -0
  130. package/dist/core/ports/github-provider.js.map +1 -0
  131. package/dist/core/ports/index.d.ts +6 -0
  132. package/dist/core/ports/index.d.ts.map +1 -0
  133. package/dist/core/ports/index.js +2 -0
  134. package/dist/core/ports/index.js.map +1 -0
  135. package/dist/core/ports/source-provider.d.ts +27 -0
  136. package/dist/core/ports/source-provider.d.ts.map +1 -0
  137. package/dist/core/ports/source-provider.js +2 -0
  138. package/dist/core/ports/source-provider.js.map +1 -0
  139. package/dist/core/ports/storage.d.ts +47 -0
  140. package/dist/core/ports/storage.d.ts.map +1 -0
  141. package/dist/core/ports/storage.js +2 -0
  142. package/dist/core/ports/storage.js.map +1 -0
  143. package/dist/core/types/config.d.ts +26 -0
  144. package/dist/core/types/config.d.ts.map +1 -0
  145. package/dist/core/types/config.js +41 -0
  146. package/dist/core/types/config.js.map +1 -0
  147. package/dist/core/types/git.d.ts +35 -0
  148. package/dist/core/types/git.d.ts.map +1 -0
  149. package/dist/core/types/git.js +6 -0
  150. package/dist/core/types/git.js.map +1 -0
  151. package/dist/core/types/github.d.ts +75 -0
  152. package/dist/core/types/github.d.ts.map +1 -0
  153. package/dist/core/types/github.js +2 -0
  154. package/dist/core/types/github.js.map +1 -0
  155. package/dist/core/types/index.d.ts +7 -0
  156. package/dist/core/types/index.d.ts.map +1 -0
  157. package/dist/core/types/index.js +2 -0
  158. package/dist/core/types/index.js.map +1 -0
  159. package/dist/core/types/issue.d.ts +74 -0
  160. package/dist/core/types/issue.d.ts.map +1 -0
  161. package/dist/core/types/issue.js +7 -0
  162. package/dist/core/types/issue.js.map +1 -0
  163. package/dist/core/types/project.d.ts +9 -0
  164. package/dist/core/types/project.d.ts.map +1 -0
  165. package/dist/core/types/project.js +5 -0
  166. package/dist/core/types/project.js.map +1 -0
  167. package/dist/db/connection.d.ts +2 -0
  168. package/dist/db/connection.d.ts.map +1 -0
  169. package/dist/db/connection.js +4 -0
  170. package/dist/db/connection.js.map +1 -0
  171. package/dist/db/import.d.ts +2 -0
  172. package/dist/db/import.d.ts.map +1 -0
  173. package/dist/db/import.js +4 -0
  174. package/dist/db/import.js.map +1 -0
  175. package/dist/db/schema.d.ts +2 -0
  176. package/dist/db/schema.d.ts.map +1 -0
  177. package/dist/db/schema.js +4 -0
  178. package/dist/db/schema.js.map +1 -0
  179. package/dist/jira/client.d.ts +2 -0
  180. package/dist/jira/client.d.ts.map +1 -0
  181. package/dist/jira/client.js +4 -0
  182. package/dist/jira/client.js.map +1 -0
  183. package/dist/jira/pull.d.ts +2 -0
  184. package/dist/jira/pull.d.ts.map +1 -0
  185. package/dist/jira/pull.js +5 -0
  186. package/dist/jira/pull.js.map +1 -0
  187. package/dist/mcp/server.d.ts +16 -0
  188. package/dist/mcp/server.d.ts.map +1 -0
  189. package/dist/mcp/server.js +1463 -0
  190. package/dist/mcp/server.js.map +1 -0
  191. package/dist/use-cases/embed.d.ts +23 -0
  192. package/dist/use-cases/embed.d.ts.map +1 -0
  193. package/dist/use-cases/embed.js +63 -0
  194. package/dist/use-cases/embed.js.map +1 -0
  195. package/dist/use-cases/pull-git.d.ts +25 -0
  196. package/dist/use-cases/pull-git.d.ts.map +1 -0
  197. package/dist/use-cases/pull-git.js +59 -0
  198. package/dist/use-cases/pull-git.js.map +1 -0
  199. package/dist/use-cases/pull-github.d.ts +28 -0
  200. package/dist/use-cases/pull-github.d.ts.map +1 -0
  201. package/dist/use-cases/pull-github.js +67 -0
  202. package/dist/use-cases/pull-github.js.map +1 -0
  203. package/dist/use-cases/pull.d.ts +32 -0
  204. package/dist/use-cases/pull.d.ts.map +1 -0
  205. package/dist/use-cases/pull.js +82 -0
  206. package/dist/use-cases/pull.js.map +1 -0
  207. package/dist/workspace/config.d.ts +36 -0
  208. package/dist/workspace/config.d.ts.map +1 -0
  209. package/dist/workspace/config.js +91 -0
  210. package/dist/workspace/config.js.map +1 -0
  211. package/dist/workspace/resolver.d.ts +19 -0
  212. package/dist/workspace/resolver.d.ts.map +1 -0
  213. package/dist/workspace/resolver.js +47 -0
  214. package/dist/workspace/resolver.js.map +1 -0
  215. package/package.json +71 -0
  216. package/templates/docker-compose.yml +26 -0
  217. package/templates/env.example +14 -0
  218. package/templates/gitignore +6 -0
  219. package/templates/init.sql +236 -0
@@ -0,0 +1,322 @@
1
+ import { createPool } from './connection.js';
2
+ import { ensureSchema } from './schema.js';
3
+ /**
4
+ * PostgreSQL adapter — implements IStorage.
5
+ *
6
+ * Uses UPSERT (ON CONFLICT) so re-pulling is safe and idempotent.
7
+ */
8
+ export class PostgresStorage {
9
+ name = 'PostgreSQL';
10
+ pool;
11
+ constructor(config) {
12
+ this.pool = createPool(config);
13
+ }
14
+ async initialize() {
15
+ await ensureSchema(this.pool);
16
+ }
17
+ async saveBatch(batch) {
18
+ const client = await this.pool.connect();
19
+ try {
20
+ await client.query('BEGIN');
21
+ // Upsert issues
22
+ for (const issue of batch.issues) {
23
+ await client.query(`INSERT INTO issues (
24
+ issue_key, issue_id, project_key, summary, description,
25
+ issue_type, status, status_category, priority, resolution,
26
+ assignee, reporter, created, updated, resolved,
27
+ due_date, labels, components, fix_versions, parent_key,
28
+ sprint, story_points, custom_fields, raw_json, pulled_at,
29
+ search_vector
30
+ ) VALUES (
31
+ $1, $2, $3, $4, $5,
32
+ $6, $7, $8, $9, $10,
33
+ $11, $12, $13, $14, $15,
34
+ $16, $17, $18, $19, $20,
35
+ $21, $22, $23, $24, NOW(),
36
+ to_tsvector('english', coalesce($4, '') || ' ' || coalesce($5, ''))
37
+ )
38
+ ON CONFLICT (issue_key) DO UPDATE SET
39
+ issue_id = EXCLUDED.issue_id,
40
+ project_key = EXCLUDED.project_key,
41
+ summary = EXCLUDED.summary,
42
+ description = EXCLUDED.description,
43
+ issue_type = EXCLUDED.issue_type,
44
+ status = EXCLUDED.status,
45
+ status_category = EXCLUDED.status_category,
46
+ priority = EXCLUDED.priority,
47
+ resolution = EXCLUDED.resolution,
48
+ assignee = EXCLUDED.assignee,
49
+ reporter = EXCLUDED.reporter,
50
+ created = EXCLUDED.created,
51
+ updated = EXCLUDED.updated,
52
+ resolved = EXCLUDED.resolved,
53
+ due_date = EXCLUDED.due_date,
54
+ labels = EXCLUDED.labels,
55
+ components = EXCLUDED.components,
56
+ fix_versions = EXCLUDED.fix_versions,
57
+ parent_key = EXCLUDED.parent_key,
58
+ sprint = EXCLUDED.sprint,
59
+ story_points = EXCLUDED.story_points,
60
+ custom_fields = EXCLUDED.custom_fields,
61
+ raw_json = EXCLUDED.raw_json,
62
+ pulled_at = NOW(),
63
+ search_vector = to_tsvector('english', coalesce(EXCLUDED.summary, '') || ' ' || coalesce(EXCLUDED.description, ''))
64
+ `, [
65
+ issue.key, issue.id, issue.projectKey, issue.summary, issue.description,
66
+ issue.issueType, issue.status, issue.statusCategory, issue.priority, issue.resolution,
67
+ issue.assignee, issue.reporter, issue.created, issue.updated, issue.resolved,
68
+ issue.dueDate, issue.labels, issue.components, issue.fixVersions, issue.parentKey,
69
+ issue.sprint, issue.storyPoints, JSON.stringify(issue.customFields), JSON.stringify(issue.rawJson),
70
+ ]);
71
+ }
72
+ // Delete old comments/changelogs/worklogs/links for these issues, then re-insert
73
+ const issueKeys = batch.issues.map((i) => i.key);
74
+ if (issueKeys.length > 0) {
75
+ const keysParam = issueKeys.map((_, i) => `$${i + 1}`).join(',');
76
+ await client.query(`DELETE FROM issue_comments WHERE issue_key IN (${keysParam})`, issueKeys);
77
+ await client.query(`DELETE FROM issue_changelogs WHERE issue_key IN (${keysParam})`, issueKeys);
78
+ await client.query(`DELETE FROM issue_worklogs WHERE issue_key IN (${keysParam})`, issueKeys);
79
+ await client.query(`DELETE FROM issue_links WHERE source_key IN (${keysParam})`, issueKeys);
80
+ }
81
+ // Insert comments
82
+ for (const c of batch.comments) {
83
+ await client.query(`INSERT INTO issue_comments (issue_key, comment_id, author, body, created, updated)
84
+ VALUES ($1, $2, $3, $4, $5, $6)`, [c.issueKey, c.commentId, c.author, c.body, c.created, c.updated]);
85
+ }
86
+ // Insert changelogs
87
+ for (const ch of batch.changelogs) {
88
+ await client.query(`INSERT INTO issue_changelogs (issue_key, author, field, from_value, to_value, changed_at)
89
+ VALUES ($1, $2, $3, $4, $5, $6)`, [ch.issueKey, ch.author, ch.field, ch.fromValue, ch.toValue, ch.changedAt]);
90
+ }
91
+ // Insert worklogs
92
+ for (const w of batch.worklogs) {
93
+ await client.query(`INSERT INTO issue_worklogs (issue_key, author, time_spent, time_spent_seconds, comment, started)
94
+ VALUES ($1, $2, $3, $4, $5, $6)`, [w.issueKey, w.author, w.timeSpent, w.timeSpentSeconds, w.comment, w.started]);
95
+ }
96
+ // Insert links
97
+ for (const l of batch.links) {
98
+ await client.query(`INSERT INTO issue_links (source_key, target_key, link_type, direction)
99
+ VALUES ($1, $2, $3, $4)`, [l.sourceKey, l.targetKey, l.linkType, l.direction]);
100
+ }
101
+ await client.query('COMMIT');
102
+ }
103
+ catch (err) {
104
+ await client.query('ROLLBACK');
105
+ throw err;
106
+ }
107
+ finally {
108
+ client.release();
109
+ }
110
+ }
111
+ async saveCommitBatch(batch) {
112
+ const client = await this.pool.connect();
113
+ try {
114
+ await client.query('BEGIN');
115
+ for (const commit of batch.commits) {
116
+ await client.query(`INSERT INTO commits (hash, message, author, email, committed_at, parents, repo_path, pulled_at, search_vector)
117
+ VALUES ($1, $2::text, $3::text, $4::text, $5, $6::text[], $7::text, NOW(),
118
+ to_tsvector('english', coalesce($2::text, '') || ' ' || coalesce($3::text, ''))
119
+ )
120
+ ON CONFLICT (hash) DO UPDATE SET
121
+ message = EXCLUDED.message,
122
+ author = EXCLUDED.author,
123
+ email = EXCLUDED.email,
124
+ committed_at = EXCLUDED.committed_at,
125
+ parents = EXCLUDED.parents,
126
+ repo_path = EXCLUDED.repo_path,
127
+ pulled_at = NOW(),
128
+ search_vector = to_tsvector('english', coalesce(EXCLUDED.message, '') || ' ' || coalesce(EXCLUDED.author, ''))`, [commit.hash, commit.message, commit.author, commit.email, commit.committedAt, commit.parents, commit.repoPath]);
129
+ }
130
+ const hashes = batch.commits.map((c) => c.hash);
131
+ if (hashes.length > 0) {
132
+ const hashesParam = hashes.map((_, i) => `$${i + 1}`).join(',');
133
+ await client.query(`DELETE FROM commit_files WHERE commit_hash IN (${hashesParam})`, hashes);
134
+ await client.query(`DELETE FROM commit_issue_refs WHERE commit_hash IN (${hashesParam})`, hashes);
135
+ }
136
+ for (const file of batch.files) {
137
+ await client.query(`INSERT INTO commit_files (commit_hash, file_path, status, additions, deletions)
138
+ VALUES ($1, $2, $3, $4, $5)`, [file.commitHash, file.filePath, file.status, file.additions, file.deletions]);
139
+ }
140
+ for (const ref of batch.issueRefs) {
141
+ await client.query(`INSERT INTO commit_issue_refs (commit_hash, issue_key)
142
+ VALUES ($1, $2)
143
+ ON CONFLICT DO NOTHING`, [ref.commitHash, ref.issueKey]);
144
+ }
145
+ await client.query('COMMIT');
146
+ }
147
+ catch (err) {
148
+ await client.query('ROLLBACK');
149
+ throw err;
150
+ }
151
+ finally {
152
+ client.release();
153
+ }
154
+ }
155
+ async getLastCommitDate(repoPath) {
156
+ const result = await this.pool.query(`SELECT MAX(committed_at) as last_date FROM commits WHERE repo_path = $1`, [repoPath]);
157
+ return result.rows[0]?.last_date ?? null;
158
+ }
159
+ async getLastUpdated(projectKey) {
160
+ const result = await this.pool.query(`SELECT MAX(updated) as last_updated FROM issues WHERE project_key = $1`, [projectKey]);
161
+ return result.rows[0]?.last_updated ?? null;
162
+ }
163
+ async saveGitHubBatch(batch) {
164
+ const client = await this.pool.connect();
165
+ try {
166
+ await client.query('BEGIN');
167
+ for (const pr of batch.pullRequests) {
168
+ await client.query(`INSERT INTO pull_requests (
169
+ number, repo_full_name, title, body, state, author,
170
+ created_at, updated_at, merged_at, closed_at,
171
+ merge_commit_sha, head_ref, base_ref,
172
+ labels, reviewers, additions, deletions, changed_files,
173
+ raw_json, pulled_at, search_vector
174
+ ) VALUES (
175
+ $1, $2, $3::text, $4::text, $5, $6,
176
+ $7, $8, $9, $10,
177
+ $11, $12, $13,
178
+ $14::text[], $15::text[], $16, $17, $18,
179
+ $19, NOW(),
180
+ to_tsvector('english', coalesce($3::text, '') || ' ' || coalesce($4::text, ''))
181
+ )
182
+ ON CONFLICT (repo_full_name, number) DO UPDATE SET
183
+ title = EXCLUDED.title,
184
+ body = EXCLUDED.body,
185
+ state = EXCLUDED.state,
186
+ author = EXCLUDED.author,
187
+ created_at = EXCLUDED.created_at,
188
+ updated_at = EXCLUDED.updated_at,
189
+ merged_at = EXCLUDED.merged_at,
190
+ closed_at = EXCLUDED.closed_at,
191
+ merge_commit_sha = EXCLUDED.merge_commit_sha,
192
+ head_ref = EXCLUDED.head_ref,
193
+ base_ref = EXCLUDED.base_ref,
194
+ labels = EXCLUDED.labels,
195
+ reviewers = EXCLUDED.reviewers,
196
+ additions = EXCLUDED.additions,
197
+ deletions = EXCLUDED.deletions,
198
+ changed_files = EXCLUDED.changed_files,
199
+ raw_json = EXCLUDED.raw_json,
200
+ pulled_at = NOW(),
201
+ search_vector = to_tsvector('english', coalesce(EXCLUDED.title, '') || ' ' || coalesce(EXCLUDED.body, ''))`, [
202
+ pr.number, pr.repoFullName, pr.title, pr.body, pr.state, pr.author,
203
+ pr.createdAt, pr.updatedAt, pr.mergedAt, pr.closedAt,
204
+ pr.mergeCommitSha, pr.headRef, pr.baseRef,
205
+ pr.labels, pr.reviewers, pr.additions, pr.deletions, pr.changedFiles,
206
+ JSON.stringify(pr.rawJson),
207
+ ]);
208
+ }
209
+ const prNumbers = batch.pullRequests.map((p) => p.number);
210
+ const repoName = batch.pullRequests[0]?.repoFullName;
211
+ if (prNumbers.length > 0 && repoName) {
212
+ const prParams = prNumbers.map((_, i) => `$${i + 2}`).join(',');
213
+ await client.query(`DELETE FROM pr_reviews WHERE repo_full_name = $1 AND pr_number IN (${prParams})`, [repoName, ...prNumbers]);
214
+ await client.query(`DELETE FROM pr_comments WHERE repo_full_name = $1 AND pr_number IN (${prParams})`, [repoName, ...prNumbers]);
215
+ await client.query(`DELETE FROM pr_files WHERE repo_full_name = $1 AND pr_number IN (${prParams})`, [repoName, ...prNumbers]);
216
+ await client.query(`DELETE FROM pr_issue_refs WHERE repo_full_name = $1 AND pr_number IN (${prParams})`, [repoName, ...prNumbers]);
217
+ }
218
+ for (const r of batch.reviews) {
219
+ await client.query(`INSERT INTO pr_reviews (pr_number, repo_full_name, review_id, reviewer, state, body, submitted_at)
220
+ VALUES ($1, $2, $3, $4, $5, $6, $7)`, [r.prNumber, r.repoFullName, r.reviewId, r.reviewer, r.state, r.body, r.submittedAt]);
221
+ }
222
+ for (const c of batch.comments) {
223
+ await client.query(`INSERT INTO pr_comments (pr_number, repo_full_name, comment_id, author, body, path, line, created_at, updated_at)
224
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`, [c.prNumber, c.repoFullName, c.commentId, c.author, c.body, c.path, c.line, c.createdAt, c.updatedAt]);
225
+ }
226
+ for (const f of batch.files) {
227
+ await client.query(`INSERT INTO pr_files (pr_number, repo_full_name, file_path, status, additions, deletions)
228
+ VALUES ($1, $2, $3, $4, $5, $6)`, [f.prNumber, f.repoFullName, f.filePath, f.status, f.additions, f.deletions]);
229
+ }
230
+ for (const ref of batch.issueRefs) {
231
+ await client.query(`INSERT INTO pr_issue_refs (pr_number, repo_full_name, issue_key)
232
+ VALUES ($1, $2, $3)
233
+ ON CONFLICT DO NOTHING`, [ref.prNumber, ref.repoFullName, ref.issueKey]);
234
+ }
235
+ await client.query('COMMIT');
236
+ }
237
+ catch (err) {
238
+ await client.query('ROLLBACK');
239
+ throw err;
240
+ }
241
+ finally {
242
+ client.release();
243
+ }
244
+ }
245
+ async saveReleases(releases) {
246
+ const client = await this.pool.connect();
247
+ try {
248
+ await client.query('BEGIN');
249
+ for (const rel of releases) {
250
+ await client.query(`INSERT INTO releases (
251
+ id, repo_full_name, tag_name, name, body, author,
252
+ draft, prerelease, created_at, published_at,
253
+ raw_json, pulled_at, search_vector
254
+ ) VALUES (
255
+ $1, $2, $3, $4::text, $5::text, $6,
256
+ $7, $8, $9, $10,
257
+ $11, NOW(),
258
+ to_tsvector('english', coalesce($4::text, '') || ' ' || coalesce($5::text, '') || ' ' || coalesce($3, ''))
259
+ )
260
+ ON CONFLICT (repo_full_name, id) DO UPDATE SET
261
+ tag_name = EXCLUDED.tag_name,
262
+ name = EXCLUDED.name,
263
+ body = EXCLUDED.body,
264
+ author = EXCLUDED.author,
265
+ draft = EXCLUDED.draft,
266
+ prerelease = EXCLUDED.prerelease,
267
+ created_at = EXCLUDED.created_at,
268
+ published_at = EXCLUDED.published_at,
269
+ raw_json = EXCLUDED.raw_json,
270
+ pulled_at = NOW(),
271
+ search_vector = to_tsvector('english', coalesce(EXCLUDED.name, '') || ' ' || coalesce(EXCLUDED.body, '') || ' ' || coalesce(EXCLUDED.tag_name, ''))`, [
272
+ rel.id, rel.repoFullName, rel.tagName, rel.name, rel.body, rel.author,
273
+ rel.draft, rel.prerelease, rel.createdAt, rel.publishedAt,
274
+ JSON.stringify(rel.rawJson),
275
+ ]);
276
+ }
277
+ await client.query('COMMIT');
278
+ }
279
+ catch (err) {
280
+ await client.query('ROLLBACK');
281
+ throw err;
282
+ }
283
+ finally {
284
+ client.release();
285
+ }
286
+ }
287
+ async getLastPrUpdated(repoFullName) {
288
+ const result = await this.pool.query(`SELECT MAX(updated_at) as last_updated FROM pull_requests WHERE repo_full_name = $1`, [repoFullName]);
289
+ return result.rows[0]?.last_updated ?? null;
290
+ }
291
+ // ─── Embedding methods ──────────────────────────────────────────────────
292
+ async getUnembeddedIssueKeys(limit) {
293
+ const result = await this.pool.query(`SELECT issue_key FROM issues WHERE embedding IS NULL ORDER BY updated DESC NULLS LAST LIMIT $1`, [limit]);
294
+ return result.rows.map((r) => r.issue_key);
295
+ }
296
+ async saveEmbedding(issueKey, vector) {
297
+ await this.pool.query(`UPDATE issues SET embedding = $1 WHERE issue_key = $2`, [`[${vector.join(',')}]`, issueKey]);
298
+ }
299
+ async semanticSearch(vector, limit, threshold) {
300
+ const vectorStr = `[${vector.join(',')}]`;
301
+ const thresholdClause = threshold !== undefined
302
+ ? `AND 1 - (embedding <=> $1::vector) >= ${String(threshold)}`
303
+ : '';
304
+ const result = await this.pool.query(`SELECT issue_key, 1 - (embedding <=> $1::vector) AS similarity
305
+ FROM issues
306
+ WHERE embedding IS NOT NULL ${thresholdClause}
307
+ ORDER BY embedding <=> $1::vector
308
+ LIMIT $2`, [vectorStr, limit]);
309
+ return result.rows.map((r) => ({
310
+ issueKey: r.issue_key,
311
+ similarity: r.similarity,
312
+ }));
313
+ }
314
+ async query(sql, params) {
315
+ const result = await this.pool.query(sql, params);
316
+ return { rows: result.rows };
317
+ }
318
+ async close() {
319
+ await this.pool.end();
320
+ }
321
+ }
322
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/adapters/postgres/storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerEmbedCommand(program: Command): void;
3
+ //# sourceMappingURL=embed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embed.d.ts","sourceRoot":"","sources":["../../src/cli/embed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8C3D"}
@@ -0,0 +1,52 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import dotenv from 'dotenv';
4
+ import { requireWorkspace } from '../workspace/resolver.js';
5
+ import { PostgresStorage } from '../adapters/postgres/index.js';
6
+ import { OpenAIEmbeddingProvider } from '../adapters/openai/index.js';
7
+ import { EmbedUseCase } from '../use-cases/embed.js';
8
+ export function registerEmbedCommand(program) {
9
+ program
10
+ .command('embed')
11
+ .description('Generate vector embeddings for issues (requires OPENAI_API_KEY)')
12
+ .option('--batch-size <n>', 'Texts per API call (default: 100)', '100')
13
+ .action(async (options) => {
14
+ try {
15
+ const workspaceRoot = requireWorkspace();
16
+ dotenv.config({ path: `${workspaceRoot}/.env` });
17
+ const apiKey = process.env['OPENAI_API_KEY'];
18
+ if (!apiKey) {
19
+ console.log(chalk.red('\n Missing OPENAI_API_KEY in .env'));
20
+ console.log(chalk.dim(' Add: OPENAI_API_KEY=sk-...'));
21
+ process.exit(1);
22
+ }
23
+ const storage = new PostgresStorage({
24
+ host: process.env['DB_HOST'] ?? 'localhost',
25
+ port: parseInt(process.env['DB_PORT'] ?? '5434', 10),
26
+ user: process.env['DB_USER'] ?? 'argustack',
27
+ password: process.env['DB_PASSWORD'] ?? 'argustack_local',
28
+ database: process.env['DB_NAME'] ?? 'argustack',
29
+ });
30
+ const embeddingProvider = new OpenAIEmbeddingProvider({ apiKey });
31
+ const useCase = new EmbedUseCase(embeddingProvider, storage);
32
+ const spinner = ora('Generating embeddings...').start();
33
+ try {
34
+ const result = await useCase.execute({
35
+ batchSize: parseInt(options.batchSize ?? '100', 10),
36
+ onProgress: (msg) => { spinner.text = msg; },
37
+ });
38
+ spinner.succeed('Embedding complete!');
39
+ console.log(chalk.green(` ${String(result.embeddedCount)} issues embedded, ${String(result.skippedCount)} skipped`));
40
+ console.log('');
41
+ }
42
+ finally {
43
+ await storage.close();
44
+ }
45
+ }
46
+ catch (err) {
47
+ console.error(chalk.red(`\n Error: ${err instanceof Error ? err.message : String(err)}`));
48
+ process.exit(1);
49
+ }
50
+ });
51
+ }
52
+ //# sourceMappingURL=embed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embed.js","sourceRoot":"","sources":["../../src/cli/embed.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,iEAAiE,CAAC;SAC9E,MAAM,CAAC,kBAAkB,EAAE,mCAAmC,EAAE,KAAK,CAAC;SACtE,MAAM,CAAC,KAAK,EAAE,OAA+B,EAAE,EAAE;QAChD,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;YACzC,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,GAAG,aAAa,OAAO,EAAE,CAAC,CAAC;YAEjD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC,CAAC;gBAC7D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC,CAAC;gBACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAED,MAAM,OAAO,GAAG,IAAI,eAAe,CAAC;gBAClC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,WAAW;gBAC3C,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,MAAM,EAAE,EAAE,CAAC;gBACpD,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,WAAW;gBAC3C,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,iBAAiB;gBACzD,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,WAAW;aAChD,CAAC,CAAC;YAEH,MAAM,iBAAiB,GAAG,IAAI,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAClE,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;YAC7D,MAAM,OAAO,GAAG,GAAG,CAAC,0BAA0B,CAAC,CAAC,KAAK,EAAE,CAAC;YAExD,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC;oBACnC,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,SAAS,IAAI,KAAK,EAAE,EAAE,CAAC;oBACnD,UAAU,EAAE,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC;iBAC7C,CAAC,CAAC;gBAEH,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;gBACvC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,qBAAqB,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC;gBACtH,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAClB,CAAC;oBAAS,CAAC;gBACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;YACxB,CAAC;QACH,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;YAC3F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { registerSourceCommands } from './sources.js';
4
+ import { registerSyncCommand } from './sync.js';
5
+ import { registerStatusCommand } from './status.js';
6
+ import { registerMcpCommands } from './mcp-install.js';
7
+ import { registerEmbedCommand } from './embed.js';
8
+ import { runInit } from './init.js';
9
+ const program = new Command();
10
+ program
11
+ .name('argustack')
12
+ .description('Project analysis platform — Jira + Git + DB')
13
+ .version('0.1.0');
14
+ // argustack init — interactive or with flags
15
+ program
16
+ .command('init')
17
+ .description('Create a new Argustack workspace')
18
+ .option('-d, --dir <path>', 'Workspace directory')
19
+ .option('-s, --source <sources>', 'Comma-separated sources: jira,git,github,db')
20
+ .option('--jira-url <url>', 'Jira instance URL')
21
+ .option('--jira-email <email>', 'Jira user email')
22
+ .option('--jira-token <token>', 'Jira API token')
23
+ .option('--jira-projects <keys>', 'Comma-separated project keys (or "all")')
24
+ .option('--git-repo <paths>', 'Git repository paths, comma-separated')
25
+ .option('--github-token <token>', 'GitHub personal access token')
26
+ .option('--github-owner <owner>', 'GitHub repository owner')
27
+ .option('--github-repo <repo>', 'GitHub repository name')
28
+ .option('--target-db-host <host>', 'Target DB host')
29
+ .option('--target-db-port <port>', 'Target DB port')
30
+ .option('--target-db-user <user>', 'Target DB user')
31
+ .option('--target-db-password <password>', 'Target DB password')
32
+ .option('--target-db-name <name>', 'Target DB name')
33
+ .option('--csv-file <path>', 'Path to Jira CSV export file')
34
+ .option('--db-port <port>', 'Argustack PostgreSQL port', '5434')
35
+ .option('--pgweb-port <port>', 'pgweb UI port', '8086')
36
+ .option('--no-interactive', 'Run without prompts (all values from flags)')
37
+ .action(async (options) => {
38
+ try {
39
+ await runInit(options);
40
+ }
41
+ catch (err) {
42
+ if (err instanceof Error && err.name === 'ExitPromptError') {
43
+ console.log('\n Cancelled.');
44
+ process.exit(0);
45
+ }
46
+ console.error(err instanceof Error ? err.message : String(err));
47
+ process.exit(1);
48
+ }
49
+ });
50
+ // argustack source list / add / enable / disable
51
+ registerSourceCommands(program);
52
+ // argustack sync [type]
53
+ registerSyncCommand(program);
54
+ // argustack status
55
+ registerStatusCommand(program);
56
+ // argustack embed
57
+ registerEmbedCommand(program);
58
+ // argustack mcp install / uninstall
59
+ const mcpCmd = program
60
+ .command('mcp')
61
+ .description('MCP server for Claude Desktop / Claude Code');
62
+ registerMcpCommands(mcpCmd);
63
+ program.parse();
64
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /** CLI flags passed from commander */
2
+ export interface InitFlags {
3
+ dir?: string;
4
+ source?: string;
5
+ jiraUrl?: string;
6
+ jiraEmail?: string;
7
+ jiraToken?: string;
8
+ jiraProjects?: string;
9
+ gitRepo?: string;
10
+ githubToken?: string;
11
+ githubOwner?: string;
12
+ githubRepo?: string;
13
+ targetDbHost?: string;
14
+ targetDbPort?: string;
15
+ targetDbUser?: string;
16
+ targetDbPassword?: string;
17
+ targetDbName?: string;
18
+ csvFile?: string;
19
+ dbPort?: string;
20
+ pgwebPort?: string;
21
+ interactive?: boolean;
22
+ }
23
+ export declare function runInit(flags?: InitFlags): Promise<void>;
24
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAwDA,sCAAsC;AACtC,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AA6mCD,wBAAsB,OAAO,CAAC,KAAK,GAAE,SAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAOlE"}