spidersan 0.4.3 → 0.5.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 (172) hide show
  1. package/CHANGELOG.md +124 -0
  2. package/README.md +95 -23
  3. package/dist/bin/spidersan.d.ts.map +1 -1
  4. package/dist/bin/spidersan.js +22 -2
  5. package/dist/bin/spidersan.js.map +1 -1
  6. package/dist/commands/abandon.d.ts.map +1 -1
  7. package/dist/commands/abandon.js +4 -2
  8. package/dist/commands/abandon.js.map +1 -1
  9. package/dist/commands/auto.js +6 -6
  10. package/dist/commands/auto.js.map +1 -1
  11. package/dist/commands/cleanup.d.ts.map +1 -1
  12. package/dist/commands/cleanup.js +3 -8
  13. package/dist/commands/cleanup.js.map +1 -1
  14. package/dist/commands/config.d.ts +7 -0
  15. package/dist/commands/config.d.ts.map +1 -1
  16. package/dist/commands/config.js +12 -0
  17. package/dist/commands/config.js.map +1 -1
  18. package/dist/commands/conflicts.d.ts.map +1 -1
  19. package/dist/commands/conflicts.js +238 -34
  20. package/dist/commands/conflicts.js.map +1 -1
  21. package/dist/commands/cross-conflicts.d.ts +17 -0
  22. package/dist/commands/cross-conflicts.d.ts.map +1 -0
  23. package/dist/commands/cross-conflicts.js +305 -0
  24. package/dist/commands/cross-conflicts.js.map +1 -0
  25. package/dist/commands/daily.d.ts +7 -0
  26. package/dist/commands/daily.d.ts.map +1 -0
  27. package/dist/commands/daily.js +171 -0
  28. package/dist/commands/daily.js.map +1 -0
  29. package/dist/commands/dashboard.d.ts +22 -0
  30. package/dist/commands/dashboard.d.ts.map +1 -0
  31. package/dist/commands/dashboard.js +401 -0
  32. package/dist/commands/dashboard.js.map +1 -0
  33. package/dist/commands/depends.js +2 -2
  34. package/dist/commands/depends.js.map +1 -1
  35. package/dist/commands/doctor.d.ts +22 -0
  36. package/dist/commands/doctor.d.ts.map +1 -1
  37. package/dist/commands/doctor.js +215 -14
  38. package/dist/commands/doctor.js.map +1 -1
  39. package/dist/commands/github-sync.d.ts +9 -0
  40. package/dist/commands/github-sync.d.ts.map +1 -0
  41. package/dist/commands/github-sync.js +180 -0
  42. package/dist/commands/github-sync.js.map +1 -0
  43. package/dist/commands/index.d.ts +11 -0
  44. package/dist/commands/index.d.ts.map +1 -1
  45. package/dist/commands/index.js +17 -0
  46. package/dist/commands/index.js.map +1 -1
  47. package/dist/commands/log.d.ts +3 -4
  48. package/dist/commands/log.d.ts.map +1 -1
  49. package/dist/commands/log.js +102 -87
  50. package/dist/commands/log.js.map +1 -1
  51. package/dist/commands/merge-order.js +8 -1
  52. package/dist/commands/merge-order.js.map +1 -1
  53. package/dist/commands/merged.d.ts.map +1 -1
  54. package/dist/commands/merged.js +4 -2
  55. package/dist/commands/merged.js.map +1 -1
  56. package/dist/commands/pulse.d.ts +6 -2
  57. package/dist/commands/pulse.d.ts.map +1 -1
  58. package/dist/commands/pulse.js +152 -202
  59. package/dist/commands/pulse.js.map +1 -1
  60. package/dist/commands/queen.d.ts +25 -0
  61. package/dist/commands/queen.d.ts.map +1 -0
  62. package/dist/commands/queen.js +309 -0
  63. package/dist/commands/queen.js.map +1 -0
  64. package/dist/commands/ready-check.d.ts +1 -0
  65. package/dist/commands/ready-check.d.ts.map +1 -1
  66. package/dist/commands/ready-check.js +43 -28
  67. package/dist/commands/ready-check.js.map +1 -1
  68. package/dist/commands/rebase-helper.d.ts +3 -0
  69. package/dist/commands/rebase-helper.d.ts.map +1 -0
  70. package/dist/commands/rebase-helper.js +52 -0
  71. package/dist/commands/rebase-helper.js.map +1 -0
  72. package/dist/commands/register.d.ts +2 -0
  73. package/dist/commands/register.d.ts.map +1 -1
  74. package/dist/commands/register.js +66 -10
  75. package/dist/commands/register.js.map +1 -1
  76. package/dist/commands/registry-sync.d.ts +9 -0
  77. package/dist/commands/registry-sync.d.ts.map +1 -0
  78. package/dist/commands/registry-sync.js +163 -0
  79. package/dist/commands/registry-sync.js.map +1 -0
  80. package/dist/commands/rescue.d.ts.map +1 -1
  81. package/dist/commands/rescue.js +69 -12
  82. package/dist/commands/rescue.js.map +1 -1
  83. package/dist/commands/stale.d.ts +16 -0
  84. package/dist/commands/stale.d.ts.map +1 -1
  85. package/dist/commands/stale.js +55 -21
  86. package/dist/commands/stale.js.map +1 -1
  87. package/dist/commands/sync-advisor.d.ts +14 -0
  88. package/dist/commands/sync-advisor.d.ts.map +1 -0
  89. package/dist/commands/sync-advisor.js +110 -0
  90. package/dist/commands/sync-advisor.js.map +1 -0
  91. package/dist/commands/sync.d.ts.map +1 -1
  92. package/dist/commands/sync.js +16 -5
  93. package/dist/commands/sync.js.map +1 -1
  94. package/dist/commands/torrent.d.ts.map +1 -1
  95. package/dist/commands/torrent.js +45 -22
  96. package/dist/commands/torrent.js.map +1 -1
  97. package/dist/commands/watch.d.ts.map +1 -1
  98. package/dist/commands/watch.js +198 -7
  99. package/dist/commands/watch.js.map +1 -1
  100. package/dist/lib/activity.d.ts +53 -0
  101. package/dist/lib/activity.d.ts.map +1 -0
  102. package/dist/lib/activity.js +267 -0
  103. package/dist/lib/activity.js.map +1 -0
  104. package/dist/lib/agent-errors.d.ts.map +1 -1
  105. package/dist/lib/agent-errors.js +3 -1
  106. package/dist/lib/agent-errors.js.map +1 -1
  107. package/dist/lib/ast.d.ts.map +1 -1
  108. package/dist/lib/ast.js +66 -19
  109. package/dist/lib/ast.js.map +1 -1
  110. package/dist/lib/colony-subscriber.d.ts +53 -0
  111. package/dist/lib/colony-subscriber.d.ts.map +1 -0
  112. package/dist/lib/colony-subscriber.js +184 -0
  113. package/dist/lib/colony-subscriber.js.map +1 -0
  114. package/dist/lib/config.d.ts +1 -0
  115. package/dist/lib/config.d.ts.map +1 -1
  116. package/dist/lib/config.js +7 -3
  117. package/dist/lib/config.js.map +1 -1
  118. package/dist/lib/crypto.d.ts.map +1 -1
  119. package/dist/lib/crypto.js +7 -3
  120. package/dist/lib/crypto.js.map +1 -1
  121. package/dist/lib/daily-bridge.d.ts +41 -0
  122. package/dist/lib/daily-bridge.d.ts.map +1 -0
  123. package/dist/lib/daily-bridge.js +185 -0
  124. package/dist/lib/daily-bridge.js.map +1 -0
  125. package/dist/lib/github.d.ts +83 -0
  126. package/dist/lib/github.d.ts.map +1 -0
  127. package/dist/lib/github.js +206 -0
  128. package/dist/lib/github.js.map +1 -0
  129. package/dist/lib/repo-scanner.d.ts +36 -0
  130. package/dist/lib/repo-scanner.d.ts.map +1 -0
  131. package/dist/lib/repo-scanner.js +159 -0
  132. package/dist/lib/repo-scanner.js.map +1 -0
  133. package/dist/lib/salvage-analyzer.d.ts +29 -0
  134. package/dist/lib/salvage-analyzer.d.ts.map +1 -0
  135. package/dist/lib/salvage-analyzer.js +122 -0
  136. package/dist/lib/salvage-analyzer.js.map +1 -0
  137. package/dist/lib/security.d.ts +15 -8
  138. package/dist/lib/security.d.ts.map +1 -1
  139. package/dist/lib/security.js +36 -1
  140. package/dist/lib/security.js.map +1 -1
  141. package/dist/lib/symbol-extractor.d.ts +41 -0
  142. package/dist/lib/symbol-extractor.d.ts.map +1 -0
  143. package/dist/lib/symbol-extractor.js +78 -0
  144. package/dist/lib/symbol-extractor.js.map +1 -0
  145. package/dist/storage/adapter.d.ts +1 -1
  146. package/dist/storage/adapter.d.ts.map +1 -1
  147. package/dist/storage/git-messages.d.ts.map +1 -1
  148. package/dist/storage/git-messages.js +57 -53
  149. package/dist/storage/git-messages.js.map +1 -1
  150. package/dist/storage/local.d.ts +1 -1
  151. package/dist/storage/local.d.ts.map +1 -1
  152. package/dist/storage/local.js +7 -5
  153. package/dist/storage/local.js.map +1 -1
  154. package/dist/storage/mycmail-adapter.d.ts.map +1 -1
  155. package/dist/storage/mycmail-adapter.js +11 -6
  156. package/dist/storage/mycmail-adapter.js.map +1 -1
  157. package/dist/storage/supabase.d.ts +21 -1
  158. package/dist/storage/supabase.d.ts.map +1 -1
  159. package/dist/storage/supabase.js +171 -6
  160. package/dist/storage/supabase.js.map +1 -1
  161. package/dist/tui/dashboard.d.ts.map +1 -1
  162. package/dist/tui/dashboard.js +15 -6
  163. package/dist/tui/dashboard.js.map +1 -1
  164. package/dist/types/cloud.d.ts +101 -0
  165. package/dist/types/cloud.d.ts.map +1 -0
  166. package/dist/types/cloud.js +13 -0
  167. package/dist/types/cloud.js.map +1 -0
  168. package/package.json +9 -6
  169. package/dist/commands/sync-all.d.ts +0 -9
  170. package/dist/commands/sync-all.d.ts.map +0 -1
  171. package/dist/commands/sync-all.js +0 -180
  172. package/dist/commands/sync-all.js.map +0 -1
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Daily Bridge — L2
3
+ * Reads treebird-internal daily collab files and filters for branch-relevant entries.
4
+ * Read-only: never writes to collab (toak owns writes).
5
+ */
6
+ export interface DailyEntry {
7
+ date: string;
8
+ time: string;
9
+ agent: string;
10
+ agentId: string;
11
+ content: string;
12
+ excerpt: string;
13
+ matchedTerms: string[];
14
+ }
15
+ export interface DailyBridgeOptions {
16
+ /** Path to daily collab directory. Defaults to TREEBIRD_DAILY or ~/Dev/treebird-internal/collab/daily */
17
+ dailyDir?: string;
18
+ /** Only parse this specific date (YYYY-MM-DD) */
19
+ date?: string;
20
+ /** How many days back to scan (default 14) */
21
+ lookback?: number;
22
+ /** Extra terms to match (branch names, file paths, etc.) */
23
+ terms?: string[];
24
+ /** Agent IDs to filter by */
25
+ agents?: string[];
26
+ /** If true, only return entries that matched at least one term */
27
+ requireMatch?: boolean;
28
+ }
29
+ /**
30
+ * Query daily collab files for branch-relevant entries.
31
+ */
32
+ export declare function queryDaily(options?: DailyBridgeOptions): DailyEntry[];
33
+ /**
34
+ * Get today's date string YYYY-MM-DD
35
+ */
36
+ export declare function todayStr(): string;
37
+ /**
38
+ * List all available daily dates (newest first)
39
+ */
40
+ export declare function listDailyDates(dailyDir?: string): string[];
41
+ //# sourceMappingURL=daily-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daily-bridge.d.ts","sourceRoot":"","sources":["../../src/lib/daily-bridge.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IAC/B,yGAAyG;IACzG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,6BAA6B;IAC7B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,kEAAkE;IAClE,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAmID;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,GAAE,kBAAuB,GAAG,UAAU,EAAE,CA2CzE;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,MAAM,CAEjC;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ1D"}
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Daily Bridge — L2
3
+ * Reads treebird-internal daily collab files and filters for branch-relevant entries.
4
+ * Read-only: never writes to collab (toak owns writes).
5
+ */
6
+ import { existsSync, readdirSync, readFileSync } from 'fs';
7
+ import { join } from 'path';
8
+ import { homedir } from 'os';
9
+ const BRANCH_KEYWORDS = [
10
+ 'merge', 'cherry-pick', 'cherry pick', 'rebase', 'conflict',
11
+ 'branch', 'abandon', 'stale', 'pr', 'pull request', 'push', 'worktree',
12
+ 'tidy', 'cleanup', 'register',
13
+ ];
14
+ const AGENT_EMOJI_MAP = {
15
+ '🌳': 'treesan',
16
+ '🐦': 'birdsan',
17
+ '🔍': 'sherlocksan',
18
+ '🍄': 'mycsan',
19
+ '🕷️': 'spidersan',
20
+ '🤖': 'codex',
21
+ '📚': 'teachersan',
22
+ '🗺️': 'mappersan',
23
+ '🌊': 'watsan',
24
+ '🦅': 'artisan',
25
+ '🐛': 'birdsan',
26
+ '💎': 'nanoclaw',
27
+ };
28
+ function getDailyDir() {
29
+ if (process.env.TREEBIRD_DAILY)
30
+ return process.env.TREEBIRD_DAILY;
31
+ const internal = process.env.TREEBIRD_INTERNAL
32
+ || join(homedir(), 'Dev', 'treebird-internal');
33
+ return join(internal, 'collab', 'daily');
34
+ }
35
+ function normaliseAgent(raw) {
36
+ // Try emoji map first
37
+ for (const [emoji, id] of Object.entries(AGENT_EMOJI_MAP)) {
38
+ if (raw.includes(emoji))
39
+ return id;
40
+ }
41
+ // Strip emoji + trim
42
+ return raw.replace(/[\p{Emoji_Presentation}\p{Extended_Pictographic}]/gu, '').trim().toLowerCase();
43
+ }
44
+ // Known non-entry table headers (Start/Stop/Continue, etc.)
45
+ const NON_ENTRY_HEADERS = new Set(['start', 'stop', 'continue', 'time', 'agent', 'entry', 'summary', 'what', 'when', 'why', 'branch', 'status', 'repo', 'owner', 'blockedby', '#']);
46
+ function looksLikeTimeOrAgent(s) {
47
+ // Time-like: HH:MM, "dawn", "today", "morning", "closing", "late", "evening", "--", "session", "afternoon"
48
+ if (/^\d{2}:\d{2}/.test(s))
49
+ return true;
50
+ if (/^(dawn|today|morning|closing|late|evening|afternoon|session|--|\d+:\d+|`\d+:\d+`)$/i.test(s))
51
+ return true;
52
+ // Agent-like: contains emoji or known agent name
53
+ if (/[\p{Emoji_Presentation}\p{Extended_Pictographic}]/u.test(s))
54
+ return true;
55
+ if (/\b(treesan|birdsan|sherlocksan|mycsan|spidersan|codex|artisan|watsan|nanoclaw|sasusan|mappersan|teachersan|copilot)\b/i.test(s))
56
+ return true;
57
+ return false;
58
+ }
59
+ function parseTableEntries(content, date) {
60
+ const entries = [];
61
+ const lines = content.split('\n');
62
+ for (const line of lines) {
63
+ // Match 3-column table rows: | col1 | col2 | col3 |
64
+ const m = line.match(/^\|\s*([^|]+?)\s*\|\s*([^|]+?)\s*\|\s*(.+?)\s*\|?\s*$/);
65
+ if (!m)
66
+ continue;
67
+ const time = m[1].trim();
68
+ const agentRaw = m[2].trim();
69
+ const entryContent = m[3].trim();
70
+ // Skip separator rows
71
+ if (time === '---' || agentRaw === '---' || entryContent === '---')
72
+ continue;
73
+ // Skip known non-entry table headers
74
+ if (NON_ENTRY_HEADERS.has(time.toLowerCase()) && NON_ENTRY_HEADERS.has(agentRaw.toLowerCase()))
75
+ continue;
76
+ // Must look like a time/agent pattern
77
+ if (!looksLikeTimeOrAgent(time) && !looksLikeTimeOrAgent(agentRaw))
78
+ continue;
79
+ // Content must be substantial (>20 chars) to be a real entry
80
+ if (!entryContent || entryContent.length < 20)
81
+ continue;
82
+ const agentId = normaliseAgent(agentRaw);
83
+ const excerpt = entryContent.replace(/\*\*/g, '').slice(0, 120) + (entryContent.length > 120 ? '…' : '');
84
+ entries.push({
85
+ date,
86
+ time,
87
+ agent: agentRaw,
88
+ agentId,
89
+ content: entryContent,
90
+ excerpt,
91
+ matchedTerms: [],
92
+ });
93
+ }
94
+ return entries;
95
+ }
96
+ function scoreEntry(entry, terms, _agents) {
97
+ const text = entry.content.toLowerCase();
98
+ const matched = [];
99
+ for (const term of terms) {
100
+ if (text.includes(term.toLowerCase())) {
101
+ matched.push(term);
102
+ }
103
+ }
104
+ // Always match branch keywords
105
+ for (const kw of BRANCH_KEYWORDS) {
106
+ if (text.includes(kw) && !matched.includes(kw)) {
107
+ matched.push(kw);
108
+ }
109
+ }
110
+ return matched;
111
+ }
112
+ function listDailyFiles(dailyDir, lookback) {
113
+ if (!existsSync(dailyDir))
114
+ return [];
115
+ const files = readdirSync(dailyDir)
116
+ .filter(f => f.match(/^\d{4}-\d{2}-\d{2}-daily\.md$/))
117
+ .sort()
118
+ .reverse();
119
+ const cutoff = new Date();
120
+ cutoff.setDate(cutoff.getDate() - lookback);
121
+ const cutoffStr = cutoff.toISOString().split('T')[0];
122
+ return files
123
+ .map(f => ({ date: f.slice(0, 10), path: join(dailyDir, f) }))
124
+ .filter(f => f.date >= cutoffStr);
125
+ }
126
+ /**
127
+ * Query daily collab files for branch-relevant entries.
128
+ */
129
+ export function queryDaily(options = {}) {
130
+ const dailyDir = options.dailyDir || getDailyDir();
131
+ const lookback = options.lookback ?? 14;
132
+ const requireMatch = options.requireMatch ?? true;
133
+ const terms = options.terms ?? [];
134
+ const agents = options.agents ?? [];
135
+ let files;
136
+ if (options.date) {
137
+ const p = join(dailyDir, `${options.date}-daily.md`);
138
+ files = existsSync(p) ? [{ date: options.date, path: p }] : [];
139
+ }
140
+ else {
141
+ files = listDailyFiles(dailyDir, lookback);
142
+ }
143
+ const results = [];
144
+ for (const { date, path } of files) {
145
+ let content;
146
+ try {
147
+ content = readFileSync(path, 'utf-8');
148
+ }
149
+ catch {
150
+ continue;
151
+ }
152
+ const entries = parseTableEntries(content, date);
153
+ for (const entry of entries) {
154
+ // Agent filter
155
+ if (agents.length > 0 && !agents.some(a => entry.agentId.includes(a.toLowerCase()))) {
156
+ continue;
157
+ }
158
+ entry.matchedTerms = scoreEntry(entry, terms, agents);
159
+ if (requireMatch && entry.matchedTerms.length === 0)
160
+ continue;
161
+ results.push(entry);
162
+ }
163
+ }
164
+ return results;
165
+ }
166
+ /**
167
+ * Get today's date string YYYY-MM-DD
168
+ */
169
+ export function todayStr() {
170
+ return new Date().toISOString().split('T')[0];
171
+ }
172
+ /**
173
+ * List all available daily dates (newest first)
174
+ */
175
+ export function listDailyDates(dailyDir) {
176
+ const dir = dailyDir || getDailyDir();
177
+ if (!existsSync(dir))
178
+ return [];
179
+ return readdirSync(dir)
180
+ .filter(f => f.match(/^\d{4}-\d{2}-\d{2}-daily\.md$/))
181
+ .map(f => f.slice(0, 10))
182
+ .sort()
183
+ .reverse();
184
+ }
185
+ //# sourceMappingURL=daily-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daily-bridge.js","sourceRoot":"","sources":["../../src/lib/daily-bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * GitHub API client wrapper using `gh` CLI
3
+ *
4
+ * Provides access to branch, PR, and CI status from GitHub
5
+ * without requiring Octokit or managing authentication.
6
+ */
7
+ export interface GitHubRepoConfig {
8
+ owner: string;
9
+ repo: string;
10
+ }
11
+ export interface GitHubBranchInfo {
12
+ name: string;
13
+ sha: string;
14
+ protected: boolean;
15
+ commit: {
16
+ sha: string;
17
+ date: string;
18
+ author: string;
19
+ message: string;
20
+ };
21
+ }
22
+ export interface GitHubPRInfo {
23
+ number: number;
24
+ title: string;
25
+ state: string;
26
+ headBranch: string;
27
+ draft: boolean;
28
+ createdAt: string;
29
+ updatedAt: string;
30
+ }
31
+ export interface GitHubCIStatus {
32
+ status: string;
33
+ conclusion: string | null;
34
+ url: string;
35
+ runId: string;
36
+ createdAt: string;
37
+ }
38
+ export interface GitHubCommitInfo {
39
+ sha: string;
40
+ date: string;
41
+ author: string;
42
+ message: string;
43
+ }
44
+ export interface AheadBehind {
45
+ ahead: number;
46
+ behind: number;
47
+ }
48
+ export interface GitHubPRDetails {
49
+ number: number;
50
+ title: string;
51
+ headBranch: string;
52
+ files: string[];
53
+ }
54
+ /**
55
+ * Check if GitHub CLI (gh) is available and authenticated.
56
+ */
57
+ export declare function isGhAvailable(): boolean;
58
+ /**
59
+ * Fetch all branches from a GitHub repository.
60
+ */
61
+ export declare function listBranches(config: GitHubRepoConfig): Promise<GitHubBranchInfo[]>;
62
+ /**
63
+ * Fetch commit details for a specific branch.
64
+ */
65
+ export declare function getCommitInfo(config: GitHubRepoConfig, branch: string): Promise<GitHubCommitInfo | null>;
66
+ /**
67
+ * Fetch all pull requests for a repository.
68
+ */
69
+ export declare function listPullRequests(config: GitHubRepoConfig): Promise<GitHubPRInfo[]>;
70
+ /**
71
+ * Get CI status for a branch (from latest workflow run).
72
+ */
73
+ export declare function getCIStatus(config: GitHubRepoConfig, branch: string): Promise<GitHubCIStatus | null>;
74
+ /**
75
+ * Compare a branch to main (or specified base) and get ahead/behind counts.
76
+ */
77
+ export declare function getAheadBehind(config: GitHubRepoConfig, branch: string, baseBranch?: string): Promise<AheadBehind>;
78
+ /**
79
+ * Fetch details for a specific pull request: head branch name and list of changed files.
80
+ * Requires `gh` CLI to be authenticated and run from inside the repository directory.
81
+ */
82
+ export declare function getPRDetails(prNumber: number): Promise<GitHubPRDetails>;
83
+ //# sourceMappingURL=github.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/lib/github.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,gBAAgB;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE;QACJ,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;KACnB,CAAC;CACL;AAED,MAAM,WAAW,YAAY;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAOvC;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA8BxF;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAgB9G;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CA0BxF;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CA0B1G;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAiBxH;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAuC7E"}
@@ -0,0 +1,206 @@
1
+ /**
2
+ * GitHub API client wrapper using `gh` CLI
3
+ *
4
+ * Provides access to branch, PR, and CI status from GitHub
5
+ * without requiring Octokit or managing authentication.
6
+ */
7
+ import { execFileSync } from 'child_process';
8
+ /**
9
+ * Check if GitHub CLI (gh) is available and authenticated.
10
+ */
11
+ export function isGhAvailable() {
12
+ try {
13
+ execFileSync('gh', ['auth', 'status'], { encoding: 'utf-8', stdio: 'pipe' });
14
+ return true;
15
+ }
16
+ catch {
17
+ return false;
18
+ }
19
+ }
20
+ /**
21
+ * Fetch all branches from a GitHub repository.
22
+ */
23
+ export async function listBranches(config) {
24
+ try {
25
+ const output = execFileSync('gh', [
26
+ 'api',
27
+ `repos/${config.owner}/${config.repo}/branches`,
28
+ '--paginate',
29
+ '--jq',
30
+ '.[] | {name: .name, sha: .commit.sha, protected: .protected}',
31
+ ], { encoding: 'utf-8' });
32
+ const branches = [];
33
+ const lines = output.trim().split('\n').filter(l => l.length > 0);
34
+ for (const line of lines) {
35
+ try {
36
+ const data = JSON.parse(line);
37
+ branches.push({
38
+ name: data.name,
39
+ sha: data.sha,
40
+ protected: data.protected,
41
+ commit: { sha: data.sha, date: '', author: '', message: '' },
42
+ });
43
+ }
44
+ catch {
45
+ // Skip invalid JSON lines
46
+ }
47
+ }
48
+ return branches;
49
+ }
50
+ catch (error) {
51
+ const msg = error instanceof Error ? error.message : String(error);
52
+ throw new Error(`Failed to list branches: ${msg}`);
53
+ }
54
+ }
55
+ /**
56
+ * Fetch commit details for a specific branch.
57
+ */
58
+ export async function getCommitInfo(config, branch) {
59
+ try {
60
+ const output = execFileSync('gh', [
61
+ 'api',
62
+ `repos/${config.owner}/${config.repo}/commits/${branch}`,
63
+ '--jq',
64
+ '{sha: .sha, date: .commit.author.date, author: .commit.author.name, message: .commit.message}',
65
+ ], { encoding: 'utf-8' });
66
+ try {
67
+ return JSON.parse(output);
68
+ }
69
+ catch {
70
+ return null;
71
+ }
72
+ }
73
+ catch {
74
+ return null;
75
+ }
76
+ }
77
+ /**
78
+ * Fetch all pull requests for a repository.
79
+ */
80
+ export async function listPullRequests(config) {
81
+ try {
82
+ const output = execFileSync('gh', [
83
+ 'pr', 'list',
84
+ '--repo', `${config.owner}/${config.repo}`,
85
+ '--state', 'all',
86
+ '--json', 'number,title,state,headRefName,isDraft,createdAt,updatedAt',
87
+ '--limit', '1000',
88
+ ], { encoding: 'utf-8' });
89
+ try {
90
+ const data = JSON.parse(output);
91
+ return data.map((pr) => ({
92
+ number: pr.number,
93
+ title: pr.title,
94
+ state: pr.state,
95
+ headBranch: pr.headRefName,
96
+ draft: pr.isDraft,
97
+ createdAt: pr.createdAt,
98
+ updatedAt: pr.updatedAt,
99
+ }));
100
+ }
101
+ catch {
102
+ return [];
103
+ }
104
+ }
105
+ catch {
106
+ return [];
107
+ }
108
+ }
109
+ /**
110
+ * Get CI status for a branch (from latest workflow run).
111
+ */
112
+ export async function getCIStatus(config, branch) {
113
+ try {
114
+ const output = execFileSync('gh', [
115
+ 'run', 'list',
116
+ '--repo', `${config.owner}/${config.repo}`,
117
+ '--branch', branch,
118
+ '--limit', '1',
119
+ '--json', 'status,conclusion,url,databaseId,createdAt',
120
+ ], { encoding: 'utf-8' });
121
+ try {
122
+ const data = JSON.parse(output);
123
+ if (!Array.isArray(data) || data.length === 0)
124
+ return null;
125
+ const run = data[0];
126
+ return {
127
+ status: run.status,
128
+ conclusion: run.conclusion,
129
+ url: run.url,
130
+ runId: String(run.databaseId),
131
+ createdAt: run.createdAt,
132
+ };
133
+ }
134
+ catch {
135
+ return null;
136
+ }
137
+ }
138
+ catch {
139
+ return null;
140
+ }
141
+ }
142
+ /**
143
+ * Compare a branch to main (or specified base) and get ahead/behind counts.
144
+ */
145
+ export async function getAheadBehind(config, branch, baseBranch = 'main') {
146
+ try {
147
+ const output = execFileSync('gh', [
148
+ 'api',
149
+ `repos/${config.owner}/${config.repo}/compare/${baseBranch}...${branch}`,
150
+ '--jq',
151
+ '{ahead: .ahead_by, behind: .behind_by}',
152
+ ], { encoding: 'utf-8' });
153
+ try {
154
+ const data = JSON.parse(output);
155
+ return { ahead: data.ahead || 0, behind: data.behind || 0 };
156
+ }
157
+ catch {
158
+ return { ahead: 0, behind: 0 };
159
+ }
160
+ }
161
+ catch {
162
+ return { ahead: 0, behind: 0 };
163
+ }
164
+ }
165
+ /**
166
+ * Fetch details for a specific pull request: head branch name and list of changed files.
167
+ * Requires `gh` CLI to be authenticated and run from inside the repository directory.
168
+ */
169
+ export async function getPRDetails(prNumber) {
170
+ if (!Number.isInteger(prNumber) || prNumber <= 0) {
171
+ throw new Error(`Invalid PR number: ${prNumber}`);
172
+ }
173
+ // Get PR metadata (head branch, title, number)
174
+ let prOutput;
175
+ try {
176
+ prOutput = execFileSync('gh', [
177
+ 'pr', 'view', String(prNumber),
178
+ '--json', 'headRefName,title,number',
179
+ ], { encoding: 'utf-8' });
180
+ }
181
+ catch (err) {
182
+ const msg = err instanceof Error ? err.message : String(err);
183
+ throw new Error(`Failed to fetch PR #${prNumber} metadata: ${msg}`);
184
+ }
185
+ const prData = JSON.parse(prOutput);
186
+ // Get changed file paths via the diff (--name-only lists one file per line)
187
+ let diffOutput;
188
+ try {
189
+ diffOutput = execFileSync('gh', [
190
+ 'pr', 'diff', String(prNumber),
191
+ '--name-only',
192
+ ], { encoding: 'utf-8' });
193
+ }
194
+ catch (err) {
195
+ const msg = err instanceof Error ? err.message : String(err);
196
+ throw new Error(`Failed to fetch changed files for PR #${prNumber}: ${msg}`);
197
+ }
198
+ const files = diffOutput.trim().split('\n').filter(f => f.length > 0);
199
+ return {
200
+ number: prData.number,
201
+ title: prData.title,
202
+ headBranch: prData.headRefName,
203
+ files,
204
+ };
205
+ }
206
+ //# sourceMappingURL=github.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/lib/github.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Multi-repo git state scanner for Smart Sync Advisor (F4)
3
+ *
4
+ * Scans all repos under a base directory and identifies:
5
+ * - Unpushed commits (ahead of remote)
6
+ * - Unpulled commits (behind remote)
7
+ * - Dirty state (uncommitted files)
8
+ * - Diverged branches (ahead AND behind)
9
+ *
10
+ * Uses execFileSync with { cwd: repoPath } — no process.chdir()
11
+ */
12
+ import type { SyncRecommendation } from '../types/cloud.js';
13
+ export interface RepoState {
14
+ name: string;
15
+ path: string;
16
+ branch: string;
17
+ unpushed: number;
18
+ unpulled: number;
19
+ isDirty: boolean;
20
+ isDiverged: boolean;
21
+ hasUpstream: boolean;
22
+ }
23
+ /**
24
+ * Scan a single repository for git state.
25
+ * Returns null if not a git repo or unreadable.
26
+ */
27
+ export declare function scanRepo(repoPath: string): RepoState | null;
28
+ /**
29
+ * Scan all repos under a base directory.
30
+ */
31
+ export declare function scanAllRepos(basePath: string): RepoState[];
32
+ /**
33
+ * Convert RepoState[] to SyncRecommendation[].
34
+ */
35
+ export declare function generateRecommendations(states: RepoState[]): SyncRecommendation[];
36
+ //# sourceMappingURL=repo-scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-scanner.d.ts","sourceRoot":"","sources":["../../src/lib/repo-scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CA0D3D;AA0BD;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,CAG1D;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,kBAAkB,EAAE,CA0CjF"}