spidersan 0.20.1 → 0.20.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.
Files changed (310) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/bin/command-registry.d.ts +25 -0
  3. package/dist/bin/command-registry.d.ts.map +1 -0
  4. package/dist/bin/command-registry.js +29 -0
  5. package/dist/bin/command-registry.js.map +1 -0
  6. package/dist/bin/spidersan.d.ts +16 -0
  7. package/dist/bin/spidersan.d.ts.map +1 -0
  8. package/dist/bin/spidersan.js +98 -0
  9. package/dist/bin/spidersan.js.map +1 -0
  10. package/dist/commands/abandon.d.ts +8 -0
  11. package/dist/commands/abandon.d.ts.map +1 -0
  12. package/dist/commands/abandon.js +43 -0
  13. package/dist/commands/abandon.js.map +1 -0
  14. package/dist/commands/cleanup.d.ts +8 -0
  15. package/dist/commands/cleanup.d.ts.map +1 -0
  16. package/dist/commands/cleanup.js +50 -0
  17. package/dist/commands/cleanup.js.map +1 -0
  18. package/dist/commands/config.d.ts +15 -0
  19. package/dist/commands/config.d.ts.map +1 -0
  20. package/dist/commands/config.js +309 -0
  21. package/dist/commands/config.js.map +1 -0
  22. package/dist/commands/conflicts.d.ts +34 -0
  23. package/dist/commands/conflicts.d.ts.map +1 -0
  24. package/dist/commands/conflicts.js +773 -0
  25. package/dist/commands/conflicts.js.map +1 -0
  26. package/dist/commands/context.d.ts +8 -0
  27. package/dist/commands/context.d.ts.map +1 -0
  28. package/dist/commands/context.js +104 -0
  29. package/dist/commands/context.js.map +1 -0
  30. package/dist/commands/cross-conflicts.d.ts +17 -0
  31. package/dist/commands/cross-conflicts.d.ts.map +1 -0
  32. package/dist/commands/cross-conflicts.js +273 -0
  33. package/dist/commands/cross-conflicts.js.map +1 -0
  34. package/dist/commands/depends.d.ts +11 -0
  35. package/dist/commands/depends.d.ts.map +1 -0
  36. package/dist/commands/depends.js +63 -0
  37. package/dist/commands/depends.js.map +1 -0
  38. package/dist/commands/doctor.d.ts +30 -0
  39. package/dist/commands/doctor.d.ts.map +1 -0
  40. package/dist/commands/doctor.js +558 -0
  41. package/dist/commands/doctor.js.map +1 -0
  42. package/dist/commands/git-watch.d.ts +24 -0
  43. package/dist/commands/git-watch.d.ts.map +1 -0
  44. package/dist/commands/git-watch.js +84 -0
  45. package/dist/commands/git-watch.js.map +1 -0
  46. package/dist/commands/github-sync.d.ts +42 -0
  47. package/dist/commands/github-sync.d.ts.map +1 -0
  48. package/dist/commands/github-sync.js +191 -0
  49. package/dist/commands/github-sync.js.map +1 -0
  50. package/dist/commands/index.d.ts +25 -0
  51. package/dist/commands/index.d.ts.map +1 -0
  52. package/dist/commands/index.js +29 -0
  53. package/dist/commands/index.js.map +1 -0
  54. package/dist/commands/init.d.ts +8 -0
  55. package/dist/commands/init.d.ts.map +1 -0
  56. package/dist/commands/init.js +23 -0
  57. package/dist/commands/init.js.map +1 -0
  58. package/dist/commands/list.d.ts +3 -0
  59. package/dist/commands/list.d.ts.map +1 -0
  60. package/dist/commands/list.js +45 -0
  61. package/dist/commands/list.js.map +1 -0
  62. package/dist/commands/log.d.ts +7 -0
  63. package/dist/commands/log.d.ts.map +1 -0
  64. package/dist/commands/log.js +110 -0
  65. package/dist/commands/log.js.map +1 -0
  66. package/dist/commands/merge-order.d.ts +9 -0
  67. package/dist/commands/merge-order.d.ts.map +1 -0
  68. package/dist/commands/merge-order.js +100 -0
  69. package/dist/commands/merge-order.js.map +1 -0
  70. package/dist/commands/merged.d.ts +8 -0
  71. package/dist/commands/merged.d.ts.map +1 -0
  72. package/dist/commands/merged.js +37 -0
  73. package/dist/commands/merged.js.map +1 -0
  74. package/dist/commands/pr-check.d.ts +24 -0
  75. package/dist/commands/pr-check.d.ts.map +1 -0
  76. package/dist/commands/pr-check.js +85 -0
  77. package/dist/commands/pr-check.js.map +1 -0
  78. package/dist/commands/ready-check.d.ts +11 -0
  79. package/dist/commands/ready-check.d.ts.map +1 -0
  80. package/dist/commands/ready-check.js +150 -0
  81. package/dist/commands/ready-check.js.map +1 -0
  82. package/dist/commands/rebase-helper.d.ts +3 -0
  83. package/dist/commands/rebase-helper.d.ts.map +1 -0
  84. package/dist/commands/rebase-helper.js +52 -0
  85. package/dist/commands/rebase-helper.js.map +1 -0
  86. package/dist/commands/register.d.ts +10 -0
  87. package/dist/commands/register.d.ts.map +1 -0
  88. package/dist/commands/register.js +176 -0
  89. package/dist/commands/register.js.map +1 -0
  90. package/dist/commands/registry-sync.d.ts +9 -0
  91. package/dist/commands/registry-sync.d.ts.map +1 -0
  92. package/dist/commands/registry-sync.js +129 -0
  93. package/dist/commands/registry-sync.js.map +1 -0
  94. package/dist/commands/stale.d.ts +17 -0
  95. package/dist/commands/stale.d.ts.map +1 -0
  96. package/dist/commands/stale.js +136 -0
  97. package/dist/commands/stale.js.map +1 -0
  98. package/dist/commands/sync.d.ts +21 -0
  99. package/dist/commands/sync.d.ts.map +1 -0
  100. package/dist/commands/sync.js +78 -0
  101. package/dist/commands/sync.js.map +1 -0
  102. package/dist/commands/verify-trunk.d.ts +18 -0
  103. package/dist/commands/verify-trunk.d.ts.map +1 -0
  104. package/dist/commands/verify-trunk.js +77 -0
  105. package/dist/commands/verify-trunk.js.map +1 -0
  106. package/dist/commands/watch.d.ts +8 -0
  107. package/dist/commands/watch.d.ts.map +1 -0
  108. package/dist/commands/watch.js +509 -0
  109. package/dist/commands/watch.js.map +1 -0
  110. package/dist/index.d.ts +8 -0
  111. package/dist/index.d.ts.map +1 -0
  112. package/dist/index.js +8 -0
  113. package/dist/index.js.map +1 -0
  114. package/dist/lib/activity.d.ts +53 -0
  115. package/dist/lib/activity.d.ts.map +1 -0
  116. package/dist/lib/activity.js +271 -0
  117. package/dist/lib/activity.js.map +1 -0
  118. package/dist/lib/agent-errors.d.ts +41 -0
  119. package/dist/lib/agent-errors.d.ts.map +1 -0
  120. package/dist/lib/agent-errors.js +145 -0
  121. package/dist/lib/agent-errors.js.map +1 -0
  122. package/dist/lib/ai/context-builder.d.ts +16 -0
  123. package/dist/lib/ai/context-builder.d.ts.map +1 -0
  124. package/dist/lib/ai/context-builder.js +229 -0
  125. package/dist/lib/ai/context-builder.js.map +1 -0
  126. package/dist/lib/ai/event-handler.d.ts +21 -0
  127. package/dist/lib/ai/event-handler.d.ts.map +1 -0
  128. package/dist/lib/ai/event-handler.js +111 -0
  129. package/dist/lib/ai/event-handler.js.map +1 -0
  130. package/dist/lib/ai/index.d.ts +13 -0
  131. package/dist/lib/ai/index.d.ts.map +1 -0
  132. package/dist/lib/ai/index.js +11 -0
  133. package/dist/lib/ai/index.js.map +1 -0
  134. package/dist/lib/ai/llm-client.d.ts +37 -0
  135. package/dist/lib/ai/llm-client.d.ts.map +1 -0
  136. package/dist/lib/ai/llm-client.js +225 -0
  137. package/dist/lib/ai/llm-client.js.map +1 -0
  138. package/dist/lib/ai/reasoner.d.ts +11 -0
  139. package/dist/lib/ai/reasoner.d.ts.map +1 -0
  140. package/dist/lib/ai/reasoner.js +227 -0
  141. package/dist/lib/ai/reasoner.js.map +1 -0
  142. package/dist/lib/ai/setup.d.ts +40 -0
  143. package/dist/lib/ai/setup.d.ts.map +1 -0
  144. package/dist/lib/ai/setup.js +154 -0
  145. package/dist/lib/ai/setup.js.map +1 -0
  146. package/dist/lib/ai/types.d.ts +135 -0
  147. package/dist/lib/ai/types.d.ts.map +1 -0
  148. package/dist/lib/ai/types.js +42 -0
  149. package/dist/lib/ai/types.js.map +1 -0
  150. package/dist/lib/ast.d.ts +44 -0
  151. package/dist/lib/ast.d.ts.map +1 -0
  152. package/dist/lib/ast.js +160 -0
  153. package/dist/lib/ast.js.map +1 -0
  154. package/dist/lib/carries.d.ts +22 -0
  155. package/dist/lib/carries.d.ts.map +1 -0
  156. package/dist/lib/carries.js +56 -0
  157. package/dist/lib/carries.js.map +1 -0
  158. package/dist/lib/colony-subscriber.d.ts +56 -0
  159. package/dist/lib/colony-subscriber.d.ts.map +1 -0
  160. package/dist/lib/colony-subscriber.js +265 -0
  161. package/dist/lib/colony-subscriber.js.map +1 -0
  162. package/dist/lib/config.d.ts +62 -0
  163. package/dist/lib/config.d.ts.map +1 -0
  164. package/dist/lib/config.js +235 -0
  165. package/dist/lib/config.js.map +1 -0
  166. package/dist/lib/conflict-analyzer.d.ts +33 -0
  167. package/dist/lib/conflict-analyzer.d.ts.map +1 -0
  168. package/dist/lib/conflict-analyzer.js +114 -0
  169. package/dist/lib/conflict-analyzer.js.map +1 -0
  170. package/dist/lib/conflict-renderer.d.ts +7 -0
  171. package/dist/lib/conflict-renderer.d.ts.map +1 -0
  172. package/dist/lib/conflict-renderer.js +145 -0
  173. package/dist/lib/conflict-renderer.js.map +1 -0
  174. package/dist/lib/conflict-tier.d.ts +20 -0
  175. package/dist/lib/conflict-tier.d.ts.map +1 -0
  176. package/dist/lib/conflict-tier.js +49 -0
  177. package/dist/lib/conflict-tier.js.map +1 -0
  178. package/dist/lib/crypto.d.ts +71 -0
  179. package/dist/lib/crypto.d.ts.map +1 -0
  180. package/dist/lib/crypto.js +176 -0
  181. package/dist/lib/crypto.js.map +1 -0
  182. package/dist/lib/ecosystem-env.d.ts +33 -0
  183. package/dist/lib/ecosystem-env.d.ts.map +1 -0
  184. package/dist/lib/ecosystem-env.js +62 -0
  185. package/dist/lib/ecosystem-env.js.map +1 -0
  186. package/dist/lib/errors.d.ts +35 -0
  187. package/dist/lib/errors.d.ts.map +1 -0
  188. package/dist/lib/errors.js +71 -0
  189. package/dist/lib/errors.js.map +1 -0
  190. package/dist/lib/git-events-subscriber.d.ts +86 -0
  191. package/dist/lib/git-events-subscriber.d.ts.map +1 -0
  192. package/dist/lib/git-events-subscriber.js +870 -0
  193. package/dist/lib/git-events-subscriber.js.map +1 -0
  194. package/dist/lib/git-merge-analyzer.d.ts +38 -0
  195. package/dist/lib/git-merge-analyzer.d.ts.map +1 -0
  196. package/dist/lib/git-merge-analyzer.js +23 -0
  197. package/dist/lib/git-merge-analyzer.js.map +1 -0
  198. package/dist/lib/git.d.ts +103 -0
  199. package/dist/lib/git.d.ts.map +1 -0
  200. package/dist/lib/git.js +670 -0
  201. package/dist/lib/git.js.map +1 -0
  202. package/dist/lib/github.d.ts +151 -0
  203. package/dist/lib/github.d.ts.map +1 -0
  204. package/dist/lib/github.js +425 -0
  205. package/dist/lib/github.js.map +1 -0
  206. package/dist/lib/graph.d.ts +38 -0
  207. package/dist/lib/graph.d.ts.map +1 -0
  208. package/dist/lib/graph.js +165 -0
  209. package/dist/lib/graph.js.map +1 -0
  210. package/dist/lib/machine.d.ts +14 -0
  211. package/dist/lib/machine.d.ts.map +1 -0
  212. package/dist/lib/machine.js +38 -0
  213. package/dist/lib/machine.js.map +1 -0
  214. package/dist/lib/notify.d.ts +68 -0
  215. package/dist/lib/notify.d.ts.map +1 -0
  216. package/dist/lib/notify.js +111 -0
  217. package/dist/lib/notify.js.map +1 -0
  218. package/dist/lib/outline.d.ts +6 -0
  219. package/dist/lib/outline.d.ts.map +1 -0
  220. package/dist/lib/outline.js +60 -0
  221. package/dist/lib/outline.js.map +1 -0
  222. package/dist/lib/push-registry.d.ts +22 -0
  223. package/dist/lib/push-registry.d.ts.map +1 -0
  224. package/dist/lib/push-registry.js +21 -0
  225. package/dist/lib/push-registry.js.map +1 -0
  226. package/dist/lib/reconcile.d.ts +100 -0
  227. package/dist/lib/reconcile.d.ts.map +1 -0
  228. package/dist/lib/reconcile.js +121 -0
  229. package/dist/lib/reconcile.js.map +1 -0
  230. package/dist/lib/regex-utils.d.ts +6 -0
  231. package/dist/lib/regex-utils.d.ts.map +1 -0
  232. package/dist/lib/regex-utils.js +24 -0
  233. package/dist/lib/regex-utils.js.map +1 -0
  234. package/dist/lib/register-renderer.d.ts +10 -0
  235. package/dist/lib/register-renderer.d.ts.map +1 -0
  236. package/dist/lib/register-renderer.js +19 -0
  237. package/dist/lib/register-renderer.js.map +1 -0
  238. package/dist/lib/remote-drift.d.ts +61 -0
  239. package/dist/lib/remote-drift.d.ts.map +1 -0
  240. package/dist/lib/remote-drift.js +227 -0
  241. package/dist/lib/remote-drift.js.map +1 -0
  242. package/dist/lib/security.d.ts +72 -0
  243. package/dist/lib/security.d.ts.map +1 -0
  244. package/dist/lib/security.js +180 -0
  245. package/dist/lib/security.js.map +1 -0
  246. package/dist/lib/semantic-analysis.d.ts +31 -0
  247. package/dist/lib/semantic-analysis.d.ts.map +1 -0
  248. package/dist/lib/semantic-analysis.js +120 -0
  249. package/dist/lib/semantic-analysis.js.map +1 -0
  250. package/dist/lib/supabase-credentials.d.ts +36 -0
  251. package/dist/lib/supabase-credentials.d.ts.map +1 -0
  252. package/dist/lib/supabase-credentials.js +43 -0
  253. package/dist/lib/supabase-credentials.js.map +1 -0
  254. package/dist/lib/trunk.d.ts +39 -0
  255. package/dist/lib/trunk.d.ts.map +1 -0
  256. package/dist/lib/trunk.js +116 -0
  257. package/dist/lib/trunk.js.map +1 -0
  258. package/dist/lib/update-check.d.ts +11 -0
  259. package/dist/lib/update-check.d.ts.map +1 -0
  260. package/dist/lib/update-check.js +113 -0
  261. package/dist/lib/update-check.js.map +1 -0
  262. package/dist/lib/watch-renderer.d.ts +13 -0
  263. package/dist/lib/watch-renderer.d.ts.map +1 -0
  264. package/dist/lib/watch-renderer.js +35 -0
  265. package/dist/lib/watch-renderer.js.map +1 -0
  266. package/dist/storage/adapter.d.ts +81 -0
  267. package/dist/storage/adapter.d.ts.map +1 -0
  268. package/dist/storage/adapter.js +8 -0
  269. package/dist/storage/adapter.js.map +1 -0
  270. package/dist/storage/branch-registry-store.d.ts +13 -0
  271. package/dist/storage/branch-registry-store.d.ts.map +1 -0
  272. package/dist/storage/branch-registry-store.js +2 -0
  273. package/dist/storage/branch-registry-store.js.map +1 -0
  274. package/dist/storage/factory.d.ts +6 -0
  275. package/dist/storage/factory.d.ts.map +1 -0
  276. package/dist/storage/factory.js +14 -0
  277. package/dist/storage/factory.js.map +1 -0
  278. package/dist/storage/index.d.ts +10 -0
  279. package/dist/storage/index.d.ts.map +1 -0
  280. package/dist/storage/index.js +11 -0
  281. package/dist/storage/index.js.map +1 -0
  282. package/dist/storage/json-branch-registry-store.d.ts +19 -0
  283. package/dist/storage/json-branch-registry-store.d.ts.map +1 -0
  284. package/dist/storage/json-branch-registry-store.js +138 -0
  285. package/dist/storage/json-branch-registry-store.js.map +1 -0
  286. package/dist/storage/local.d.ts +20 -0
  287. package/dist/storage/local.d.ts.map +1 -0
  288. package/dist/storage/local.js +40 -0
  289. package/dist/storage/local.js.map +1 -0
  290. package/dist/storage/memory-branch-registry-store.d.ts +16 -0
  291. package/dist/storage/memory-branch-registry-store.d.ts.map +1 -0
  292. package/dist/storage/memory-branch-registry-store.js +68 -0
  293. package/dist/storage/memory-branch-registry-store.js.map +1 -0
  294. package/dist/storage/supabase-registry-sync-client-impl.d.ts +40 -0
  295. package/dist/storage/supabase-registry-sync-client-impl.d.ts.map +1 -0
  296. package/dist/storage/supabase-registry-sync-client-impl.js +278 -0
  297. package/dist/storage/supabase-registry-sync-client-impl.js.map +1 -0
  298. package/dist/storage/supabase-registry-sync-client.d.ts +9 -0
  299. package/dist/storage/supabase-registry-sync-client.d.ts.map +1 -0
  300. package/dist/storage/supabase-registry-sync-client.js +2 -0
  301. package/dist/storage/supabase-registry-sync-client.js.map +1 -0
  302. package/dist/storage/supabase.d.ts +28 -0
  303. package/dist/storage/supabase.d.ts.map +1 -0
  304. package/dist/storage/supabase.js +56 -0
  305. package/dist/storage/supabase.js.map +1 -0
  306. package/dist/types/cloud.d.ts +102 -0
  307. package/dist/types/cloud.d.ts.map +1 -0
  308. package/dist/types/cloud.js +13 -0
  309. package/dist/types/cloud.js.map +1 -0
  310. package/package.json +1 -1
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Reconcile-on-read (tb-8sa.1 step 2)
3
+ *
4
+ * The registry's `status` field is only as fresh as the last `spidersan merged`
5
+ * / `sync` call — and a committed registry snapshot can carry an `active` entry
6
+ * for a branch that has since merged. Trusting that stale status is what
7
+ * produced the phantom-conflict incident (a fully-merged branch still flagged
8
+ * as conflicting from a stale worktree).
9
+ *
10
+ * Reconcile-on-read folds git truth in BEFORE conflicts / ready-check /
11
+ * merge-order answer:
12
+ * - ref gone from local AND remote → orphaned (drop)
13
+ * - tip is an ancestor of trunk → merged (drop)
14
+ * - trunk has a patch-id-equivalent squash → merged (drop, tb-tr1z)
15
+ * - otherwise → live (keep)
16
+ *
17
+ * It only consults git for entries the registry still calls `active`; entries
18
+ * already marked `completed` / `abandoned` are honoured without a git probe.
19
+ */
20
+ import type { Branch } from '../storage/adapter.js';
21
+ export interface ReconcileResult {
22
+ /** Branches still genuinely in flight — the set readers should act on. */
23
+ live: Branch[];
24
+ /** Names detected as merged into trunk (by status or by is-ancestor). */
25
+ merged: string[];
26
+ /** Names whose ref is gone from both local and remote. */
27
+ orphaned: string[];
28
+ }
29
+ /**
30
+ * Injectable git probes so reconcile is unit-testable without a real repo.
31
+ * Defaults wire to the real `git.ts` helpers via {@link defaultReconcileDeps}.
32
+ */
33
+ export interface ReconcileDeps {
34
+ /** Resolve a branch name to a usable ref, or `null` if no ref exists. */
35
+ resolveRef: (name: string) => string | null;
36
+ /**
37
+ * Resolve the LOCAL ref (`refs/heads/<name>`), or `null` if none. When the
38
+ * primary ref is the remote-tracking one, a stale `origin/<name>` can be an
39
+ * ancestor of trunk while fresh unpushed local commits are not — both must
40
+ * be merged before the branch is reconciled away. Optional for injectors.
41
+ */
42
+ resolveLocalRef?: (name: string) => string | null;
43
+ /** True if `ref` is fully merged into `trunkRef`. */
44
+ isMerged: (ref: string, trunkRef: string) => boolean;
45
+ /**
46
+ * True if `ref`'s content landed in trunk via a SQUASH merge (tb-tr1z) —
47
+ * consulted only when `isMerged` says no, since squash merges never make
48
+ * the tip an ancestor. Optional for injectors.
49
+ */
50
+ isSquashMerged?: (ref: string, trunkRef: string) => boolean;
51
+ /**
52
+ * Branch names that exist on the remote now, or `null` if it can't be asked.
53
+ * {@link activeBranches} drops an orphan only when this confirms it is gone.
54
+ * Absent (injectors) behaves like `null`: orphans are kept.
55
+ */
56
+ remoteHeads?: () => Set<string> | null;
57
+ /** Bare trunk branch name (e.g. `main`) — never reconciled away. */
58
+ trunkName: string;
59
+ /** Ref used as the merge target for is-ancestor (prefers `origin/main`). */
60
+ trunkRef: string;
61
+ }
62
+ export declare function defaultReconcileDeps(): ReconcileDeps;
63
+ /**
64
+ * Partition registered branches into live / merged / orphaned using git truth.
65
+ *
66
+ * @param branches the raw registry entries (e.g. `await storage.list()`)
67
+ * @param deps git probes; defaults to the real repo
68
+ */
69
+ export declare function reconcileBranches(branches: Branch[], deps?: ReconcileDeps): ReconcileResult;
70
+ /**
71
+ * Read-path convenience for conflict detection: registered `active` branches
72
+ * minus those PROVEN merged into trunk (is-ancestor / squash-equivalent, or
73
+ * status `completed`) and those PROVEN deleted.
74
+ *
75
+ * An orphan (no local or tracking ref) is ambiguous: deleted, or live on
76
+ * another machine and never fetched here. A squash-merged, deleted branch is
77
+ * never an ancestor of trunk, so it only ever reads as orphaned — keeping every
78
+ * orphan made those phantom-conflict forever. So an orphan is dropped only when
79
+ * `git ls-remote` confirms the branch is gone from the remote; if the remote
80
+ * can't be asked, orphans are kept (a phantom beats a missed conflict). This
81
+ * matters most for ready-check, which gets no cross-machine registry pull.
82
+ *
83
+ * Read-side filter only — nothing is deleted. This is what conflicts /
84
+ * ready-check / merge-order should call; `sync` uses {@link reconcileBranches}
85
+ * directly to actually prune merged and orphaned entries.
86
+ */
87
+ export declare function activeBranches(branches: Branch[], deps?: ReconcileDeps): Branch[];
88
+ /**
89
+ * Split orphans (no local or tracking ref) into those the remote confirms are
90
+ * `gone` and those to `kept` — still on the remote (unfetched here), or every
91
+ * one of them when the remote can't be asked (`remoteChecked: false`). Shared by
92
+ * {@link activeBranches} (read side) and `sync` (which deletes `gone` only, sp-slemub).
93
+ * Only hits the network when there is an orphan to decide.
94
+ */
95
+ export declare function splitOrphans(orphaned: string[], deps?: Pick<ReconcileDeps, 'remoteHeads'>): {
96
+ gone: string[];
97
+ kept: string[];
98
+ remoteChecked: boolean;
99
+ };
100
+ //# sourceMappingURL=reconcile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../src/lib/reconcile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC5B,0EAA0E;IAC1E,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,yEAAyE;IACzE,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC1B,yEAAyE;IACzE,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC5C;;;;;OAKG;IACH,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAClD,qDAAqD;IACrD,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IACrD;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IAC5D;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IACvC,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,oBAAoB,IAAI,aAAa,CAapD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC7B,QAAQ,EAAE,MAAM,EAAE,EAClB,IAAI,GAAE,aAAsC,GAC7C,eAAe,CA+CjB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,IAAI,GAAE,aAAsC,GAAG,MAAM,EAAE,CAIzG;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CACxB,QAAQ,EAAE,MAAM,EAAE,EAClB,IAAI,GAAE,IAAI,CAAC,aAAa,EAAE,aAAa,CAA4C,GACpF;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,EAAE,OAAO,CAAA;CAAE,CAK5D"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Reconcile-on-read (tb-8sa.1 step 2)
3
+ *
4
+ * The registry's `status` field is only as fresh as the last `spidersan merged`
5
+ * / `sync` call — and a committed registry snapshot can carry an `active` entry
6
+ * for a branch that has since merged. Trusting that stale status is what
7
+ * produced the phantom-conflict incident (a fully-merged branch still flagged
8
+ * as conflicting from a stale worktree).
9
+ *
10
+ * Reconcile-on-read folds git truth in BEFORE conflicts / ready-check /
11
+ * merge-order answer:
12
+ * - ref gone from local AND remote → orphaned (drop)
13
+ * - tip is an ancestor of trunk → merged (drop)
14
+ * - trunk has a patch-id-equivalent squash → merged (drop, tb-tr1z)
15
+ * - otherwise → live (keep)
16
+ *
17
+ * It only consults git for entries the registry still calls `active`; entries
18
+ * already marked `completed` / `abandoned` are honoured without a git probe.
19
+ */
20
+ import { resolveBranchRef, resolveLocalBranchRef, isMergedInto, isSquashMergedInto, listRemoteHeads } from './git.js';
21
+ import { getTrunkBranch } from './trunk.js';
22
+ export function defaultReconcileDeps() {
23
+ const trunkName = getTrunkBranch();
24
+ // Prefer the remote trunk ref so a stale local `main` can't mask merges.
25
+ const trunkRef = resolveBranchRef(trunkName) ?? trunkName;
26
+ return {
27
+ resolveRef: (name) => resolveBranchRef(name),
28
+ resolveLocalRef: (name) => resolveLocalBranchRef(name),
29
+ isMerged: (ref, trunk) => isMergedInto(ref, trunk),
30
+ isSquashMerged: (ref, trunk) => isSquashMergedInto(ref, trunk),
31
+ remoteHeads: () => listRemoteHeads(),
32
+ trunkName,
33
+ trunkRef,
34
+ };
35
+ }
36
+ /**
37
+ * Partition registered branches into live / merged / orphaned using git truth.
38
+ *
39
+ * @param branches the raw registry entries (e.g. `await storage.list()`)
40
+ * @param deps git probes; defaults to the real repo
41
+ */
42
+ export function reconcileBranches(branches, deps = defaultReconcileDeps()) {
43
+ const live = [];
44
+ const merged = [];
45
+ const orphaned = [];
46
+ for (const branch of branches) {
47
+ // The trunk itself is never "in flight" but also never reconciled away —
48
+ // pass it through unchanged so readers keep their existing handling.
49
+ if (branch.name === deps.trunkName) {
50
+ live.push(branch);
51
+ continue;
52
+ }
53
+ // Honour terminal registry status without a git probe.
54
+ if (branch.status === 'completed') {
55
+ merged.push(branch.name);
56
+ continue;
57
+ }
58
+ if (branch.status === 'abandoned') {
59
+ orphaned.push(branch.name);
60
+ continue;
61
+ }
62
+ // status === 'active' — fold in git truth. Squash merges never make
63
+ // the tip an ancestor, so fall back to patch-id equivalence (tb-tr1z).
64
+ const provenMerged = (r) => deps.isMerged(r, deps.trunkRef) || (deps.isSquashMerged?.(r, deps.trunkRef) ?? false);
65
+ const ref = deps.resolveRef(branch.name);
66
+ if (ref === null) {
67
+ orphaned.push(branch.name);
68
+ continue;
69
+ }
70
+ if (provenMerged(ref)) {
71
+ // The primary ref may be a stale origin/<name> while unpushed local
72
+ // commits exist — only reconcile away if the local tip (when it
73
+ // exists and differs) is merged too.
74
+ const localRef = deps.resolveLocalRef?.(branch.name) ?? null;
75
+ if (localRef === null || localRef === ref || provenMerged(localRef)) {
76
+ merged.push(branch.name);
77
+ continue;
78
+ }
79
+ }
80
+ live.push(branch);
81
+ }
82
+ return { live, merged, orphaned };
83
+ }
84
+ /**
85
+ * Read-path convenience for conflict detection: registered `active` branches
86
+ * minus those PROVEN merged into trunk (is-ancestor / squash-equivalent, or
87
+ * status `completed`) and those PROVEN deleted.
88
+ *
89
+ * An orphan (no local or tracking ref) is ambiguous: deleted, or live on
90
+ * another machine and never fetched here. A squash-merged, deleted branch is
91
+ * never an ancestor of trunk, so it only ever reads as orphaned — keeping every
92
+ * orphan made those phantom-conflict forever. So an orphan is dropped only when
93
+ * `git ls-remote` confirms the branch is gone from the remote; if the remote
94
+ * can't be asked, orphans are kept (a phantom beats a missed conflict). This
95
+ * matters most for ready-check, which gets no cross-machine registry pull.
96
+ *
97
+ * Read-side filter only — nothing is deleted. This is what conflicts /
98
+ * ready-check / merge-order should call; `sync` uses {@link reconcileBranches}
99
+ * directly to actually prune merged and orphaned entries.
100
+ */
101
+ export function activeBranches(branches, deps = defaultReconcileDeps()) {
102
+ const { live, orphaned } = reconcileBranches(branches, deps);
103
+ const keep = new Set([...live.map(b => b.name), ...splitOrphans(orphaned, deps).kept]);
104
+ return branches.filter(b => b.status === 'active' && keep.has(b.name));
105
+ }
106
+ /**
107
+ * Split orphans (no local or tracking ref) into those the remote confirms are
108
+ * `gone` and those to `kept` — still on the remote (unfetched here), or every
109
+ * one of them when the remote can't be asked (`remoteChecked: false`). Shared by
110
+ * {@link activeBranches} (read side) and `sync` (which deletes `gone` only, sp-slemub).
111
+ * Only hits the network when there is an orphan to decide.
112
+ */
113
+ export function splitOrphans(orphaned, deps = { remoteHeads: () => listRemoteHeads() }) {
114
+ if (orphaned.length === 0)
115
+ return { gone: [], kept: [], remoteChecked: true };
116
+ const heads = deps.remoteHeads?.() ?? null;
117
+ if (heads === null)
118
+ return { gone: [], kept: orphaned, remoteChecked: false };
119
+ return { gone: orphaned.filter(n => !heads.has(n)), kept: orphaned.filter(n => heads.has(n)), remoteChecked: true };
120
+ }
121
+ //# sourceMappingURL=reconcile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../../src/lib/reconcile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Utility for combining multiple Regular Expressions into a single efficient RegExp.
3
+ * Consolidates patterns using the OR (|) operator to reduce matching complexity from O(N*M) to O(1).
4
+ */
5
+ export declare function compilePatterns(patterns: RegExp[]): RegExp[];
6
+ //# sourceMappingURL=regex-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regex-utils.d.ts","sourceRoot":"","sources":["../../src/lib/regex-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAqB5D"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Utility for combining multiple Regular Expressions into a single efficient RegExp.
3
+ * Consolidates patterns using the OR (|) operator to reduce matching complexity from O(N*M) to O(1).
4
+ */
5
+ export function compilePatterns(patterns) {
6
+ if (!patterns || patterns.length === 0)
7
+ return [];
8
+ // Group patterns by their flags to preserve behavior (e.g., 'i', 'g', 'm')
9
+ const grouped = new Map();
10
+ for (const p of patterns) {
11
+ const flags = p.flags;
12
+ if (!grouped.has(flags)) {
13
+ grouped.set(flags, []);
14
+ }
15
+ // Use non-capturing groups to ensure OR logic applies correctly to the whole pattern
16
+ grouped.get(flags).push(`(?:${p.source})`);
17
+ }
18
+ const result = [];
19
+ for (const [flags, sources] of grouped.entries()) {
20
+ result.push(new RegExp(sources.join('|'), flags));
21
+ }
22
+ return result;
23
+ }
24
+ //# sourceMappingURL=regex-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regex-utils.js","sourceRoot":"","sources":["../../src/lib/regex-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAAkB;IAC9C,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAElD,2EAA2E;IAC3E,MAAM,OAAO,GAAG,IAAI,GAAG,EAAoB,CAAC;IAE5C,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;QACtB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC3B,CAAC;QACD,qFAAqF;QACrF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;QAC/C,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC"}
@@ -0,0 +1,10 @@
1
+ export interface RegisterRenderOptions {
2
+ branchName: string;
3
+ files: string[];
4
+ isUpdate: boolean;
5
+ autoDetected?: boolean;
6
+ autoDetectedFiles?: string[];
7
+ }
8
+ /** Pure. Returns terminal string for spidersan register success output. */
9
+ export declare function renderRegisterResult(opts: RegisterRenderOptions): string;
10
+ //# sourceMappingURL=register-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-renderer.d.ts","sourceRoot":"","sources":["../../src/lib/register-renderer.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC;AAED,2EAA2E;AAC3E,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,qBAAqB,GAAG,MAAM,CAmBxE"}
@@ -0,0 +1,19 @@
1
+ /** Pure. Returns terminal string for spidersan register success output. */
2
+ export function renderRegisterResult(opts) {
3
+ const lines = [];
4
+ const detectedFiles = opts.autoDetectedFiles ?? opts.files;
5
+ if (opts.autoDetected && detectedFiles.length > 0) {
6
+ lines.push(`🕷️ Auto-detected ${detectedFiles.length} changed file(s)`);
7
+ }
8
+ if (opts.isUpdate) {
9
+ lines.push(`🕷️ Updated branch: ${opts.branchName}`);
10
+ }
11
+ else {
12
+ lines.push(`🕷️ Registered branch: ${opts.branchName}`);
13
+ }
14
+ if (opts.files.length > 0) {
15
+ lines.push(` Files: ${opts.files.join(', ')}`);
16
+ }
17
+ return lines.join('\n').trimEnd();
18
+ }
19
+ //# sourceMappingURL=register-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-renderer.js","sourceRoot":"","sources":["../../src/lib/register-renderer.ts"],"names":[],"mappings":"AAQA,2EAA2E;AAC3E,MAAM,UAAU,oBAAoB,CAAC,IAA2B;IAC5D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,aAAa,GAAG,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,KAAK,CAAC;IAE3D,IAAI,IAAI,CAAC,YAAY,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,qBAAqB,aAAa,CAAC,MAAM,kBAAkB,CAAC,CAAC;IAC5E,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,KAAK,CAAC,IAAI,CAAC,uBAAuB,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IACzD,CAAC;SAAM,CAAC;QACJ,KAAK,CAAC,IAAI,CAAC,0BAA0B,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;AACtC,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * remote-drift.ts
3
+ *
4
+ * Detects whether origin/main has advanced past local HEAD and cross-references
5
+ * the drift zone against (a) the registered file list and (b) unstaged tracked
6
+ * files in the working tree.
7
+ *
8
+ * Core primitives (getDriftZone, getUnstagedTrackedFiles, classifyDriftZone)
9
+ * are exported so that watch --fetch-poll can reuse them without importing
10
+ * from the command layer.
11
+ */
12
+ export interface DriftEntry {
13
+ file: string;
14
+ registered: boolean;
15
+ tier: 1 | 2 | 3 | null;
16
+ unstaged: boolean;
17
+ }
18
+ export interface DriftResult {
19
+ branch: string;
20
+ remote: string;
21
+ localAhead: number;
22
+ remoteAhead: number;
23
+ state: 'synced' | 'local_ahead' | 'remote_ahead' | 'diverged';
24
+ driftZone: string[];
25
+ registeredInDrift: DriftEntry[];
26
+ unstagedInDrift: DriftEntry[];
27
+ safeToPush: boolean;
28
+ rebaseContinueRisk: boolean;
29
+ recommendation: 'synced' | 'push_clean' | 'pull_rebase' | 'rebase_clean' | 'rebase_with_conflict_prep';
30
+ }
31
+ export interface DriftSkipped {
32
+ skipped: true;
33
+ reason: string;
34
+ }
35
+ export declare function isOfflineError(error: unknown): boolean;
36
+ /**
37
+ * Returns the union of files touched by commits that origin/<branch> has but
38
+ * local HEAD does not. Requires a prior `git fetch origin`.
39
+ */
40
+ export declare function getDriftZone(remote: string, branch: string): string[];
41
+ /**
42
+ * Returns tracked files that have unstaged modifications (working tree vs index).
43
+ */
44
+ export declare function getUnstagedTrackedFiles(): string[];
45
+ /**
46
+ * Cross-references driftFiles against registeredFiles + unstagedFiles.
47
+ * Returns a DriftEntry for each file in the drift zone.
48
+ */
49
+ export declare function classifyDriftZone(driftFiles: string[], registeredFiles: string[], unstagedFiles: string[], tierOptions?: {
50
+ extraTier3?: RegExp[];
51
+ extraTier2?: RegExp[];
52
+ }): DriftEntry[];
53
+ /**
54
+ * Main entry point. Fetches origin, computes drift, classifies against registry
55
+ * and working tree. Returns DriftSkipped for graceful-degradation cases.
56
+ */
57
+ export declare function computeDriftResult(registeredFiles: string[], options?: {
58
+ remote?: string;
59
+ branch?: string;
60
+ }): Promise<DriftResult | DriftSkipped>;
61
+ //# sourceMappingURL=remote-drift.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-drift.d.ts","sourceRoot":"","sources":["../../src/lib/remote-drift.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AASH,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,QAAQ,GAAG,aAAa,GAAG,cAAc,GAAG,UAAU,CAAC;IAC9D,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,iBAAiB,EAAE,UAAU,EAAE,CAAC;IAChC,eAAe,EAAE,UAAU,EAAE,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,cAAc,EAAE,QAAQ,GAAG,YAAY,GAAG,aAAa,GAAG,cAAc,GAAG,2BAA2B,CAAC;CAC1G;AAED,MAAM,WAAW,YAAY;IACzB,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAClB;AAYD,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAGtD;AAcD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAgCrE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,EAAE,CAOlD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC7B,UAAU,EAAE,MAAM,EAAE,EACpB,eAAe,EAAE,MAAM,EAAE,EACzB,aAAa,EAAE,MAAM,EAAE,EACvB,WAAW,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAC/D,UAAU,EAAE,CAgBd;AAuBD;;;GAGG;AACH,wBAAsB,kBAAkB,CACpC,eAAe,EAAE,MAAM,EAAE,EACzB,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C,OAAO,CAAC,WAAW,GAAG,YAAY,CAAC,CAuGrC"}
@@ -0,0 +1,227 @@
1
+ /**
2
+ * remote-drift.ts
3
+ *
4
+ * Detects whether origin/main has advanced past local HEAD and cross-references
5
+ * the drift zone against (a) the registered file list and (b) unstaged tracked
6
+ * files in the working tree.
7
+ *
8
+ * Core primitives (getDriftZone, getUnstagedTrackedFiles, classifyDriftZone)
9
+ * are exported so that watch --fetch-poll can reuse them without importing
10
+ * from the command layer.
11
+ */
12
+ import { execFileSync } from 'child_process';
13
+ import * as fs from 'fs';
14
+ import * as path from 'path';
15
+ import { getCurrentBranch, getAheadBehind } from './git.js';
16
+ import { classifyTier } from './conflict-tier.js';
17
+ import { validateBranchName } from './security.js';
18
+ const GIT_TIMEOUT_MS = 15_000;
19
+ function execGit(args) {
20
+ return execFileSync('git', args, {
21
+ encoding: 'utf-8',
22
+ env: { ...process.env },
23
+ timeout: GIT_TIMEOUT_MS,
24
+ });
25
+ }
26
+ export function isOfflineError(error) {
27
+ const msg = String(error instanceof Error ? error.message : error);
28
+ return /ENOTFOUND|ETIMEDOUT|ECONNREFUSED|network|Could not resolve host|unable to connect|cannot access/i.test(msg);
29
+ }
30
+ function isInRebase() {
31
+ try {
32
+ const gitDir = execGit(['rev-parse', '--git-dir']).trim();
33
+ return (fs.existsSync(path.join(gitDir, 'rebase-merge')) ||
34
+ fs.existsSync(path.join(gitDir, 'rebase-apply')));
35
+ }
36
+ catch {
37
+ return false;
38
+ }
39
+ }
40
+ /**
41
+ * Returns the union of files touched by commits that origin/<branch> has but
42
+ * local HEAD does not. Requires a prior `git fetch origin`.
43
+ */
44
+ export function getDriftZone(remote, branch) {
45
+ const safeBranch = validateBranchName(branch);
46
+ const upstreamRef = `${remote}/${safeBranch}`;
47
+ let commitList;
48
+ try {
49
+ commitList = execGit(['rev-list', `HEAD..${upstreamRef}`]).trim();
50
+ }
51
+ catch {
52
+ return [];
53
+ }
54
+ if (!commitList)
55
+ return [];
56
+ const shas = commitList.split('\n').filter(Boolean);
57
+ const files = new Set();
58
+ for (const sha of shas) {
59
+ try {
60
+ const stat = execGit(['show', '--stat', '--format=', sha]);
61
+ for (const line of stat.split('\n')) {
62
+ // Lines like: " src/lib/git.ts | 10 ++--"
63
+ const match = /^\s+(.+?)\s+\|/.exec(line);
64
+ if (match && match[1]) {
65
+ files.add(match[1].trim());
66
+ }
67
+ }
68
+ }
69
+ catch {
70
+ // skip unparseable commit
71
+ }
72
+ }
73
+ return [...files];
74
+ }
75
+ /**
76
+ * Returns tracked files that have unstaged modifications (working tree vs index).
77
+ */
78
+ export function getUnstagedTrackedFiles() {
79
+ try {
80
+ const output = execGit(['diff', '--name-only']).trim();
81
+ return output ? output.split('\n').filter(Boolean) : [];
82
+ }
83
+ catch {
84
+ return [];
85
+ }
86
+ }
87
+ /**
88
+ * Cross-references driftFiles against registeredFiles + unstagedFiles.
89
+ * Returns a DriftEntry for each file in the drift zone.
90
+ */
91
+ export function classifyDriftZone(driftFiles, registeredFiles, unstagedFiles, tierOptions) {
92
+ const registeredSet = new Set(registeredFiles);
93
+ const unstagedSet = new Set(unstagedFiles);
94
+ return driftFiles.map((file) => {
95
+ const registered = registeredSet.has(file);
96
+ const unstaged = unstagedSet.has(file);
97
+ const tier = registered
98
+ ? classifyTier(file, {
99
+ extraTier3: tierOptions?.extraTier3 ?? [],
100
+ extraTier2: tierOptions?.extraTier2 ?? [],
101
+ })
102
+ : null;
103
+ return { file, registered, tier, unstaged };
104
+ });
105
+ }
106
+ function deriveState(localAhead, remoteAhead) {
107
+ if (localAhead === 0 && remoteAhead === 0)
108
+ return 'synced';
109
+ if (localAhead > 0 && remoteAhead === 0)
110
+ return 'local_ahead';
111
+ if (localAhead === 0 && remoteAhead > 0)
112
+ return 'remote_ahead';
113
+ return 'diverged';
114
+ }
115
+ function deriveRecommendation(state, registeredInDrift, unstagedInDrift) {
116
+ if (state === 'synced')
117
+ return 'synced';
118
+ if (state === 'local_ahead')
119
+ return 'push_clean';
120
+ // remote_ahead or diverged
121
+ if (registeredInDrift.length > 0 || unstagedInDrift.length > 0) {
122
+ return 'rebase_with_conflict_prep';
123
+ }
124
+ return state === 'diverged' ? 'rebase_clean' : 'pull_rebase';
125
+ }
126
+ /**
127
+ * Main entry point. Fetches origin, computes drift, classifies against registry
128
+ * and working tree. Returns DriftSkipped for graceful-degradation cases.
129
+ */
130
+ export async function computeDriftResult(registeredFiles, options) {
131
+ const remote = options?.remote ?? 'origin';
132
+ // Detect mid-rebase
133
+ if (isInRebase()) {
134
+ return { skipped: true, reason: 'Rebase in progress — run after completing or aborting rebase' };
135
+ }
136
+ // Determine branch
137
+ let branch;
138
+ try {
139
+ branch = options?.branch ?? getCurrentBranch();
140
+ }
141
+ catch {
142
+ return { skipped: true, reason: 'Not in a git repository' };
143
+ }
144
+ if (branch === 'HEAD') {
145
+ return { skipped: true, reason: 'Detached HEAD — cannot determine branch' };
146
+ }
147
+ // Fetch
148
+ try {
149
+ execGit(['fetch', remote]);
150
+ }
151
+ catch (error) {
152
+ if (isOfflineError(error)) {
153
+ return { skipped: true, reason: '⚠ Remote unreachable — drift check skipped' };
154
+ }
155
+ const msg = error instanceof Error ? error.message : String(error);
156
+ if (/No such remote|remote .* not found/i.test(msg)) {
157
+ return { skipped: true, reason: `No remote '${remote}' found` };
158
+ }
159
+ // Unknown fetch error — still skip gracefully
160
+ return { skipped: true, reason: `Fetch failed: ${msg}` };
161
+ }
162
+ // Check if remote branch exists
163
+ const safeBranch = validateBranchName(branch);
164
+ const upstreamRef = `${remote}/${safeBranch}`;
165
+ try {
166
+ execGit(['rev-parse', '--verify', upstreamRef]);
167
+ }
168
+ catch {
169
+ // Remote branch doesn't exist yet (first push)
170
+ return {
171
+ branch,
172
+ remote: upstreamRef,
173
+ localAhead: 0,
174
+ remoteAhead: 0,
175
+ state: 'synced',
176
+ driftZone: [],
177
+ registeredInDrift: [],
178
+ unstagedInDrift: [],
179
+ safeToPush: true,
180
+ rebaseContinueRisk: false,
181
+ recommendation: 'push_clean',
182
+ };
183
+ }
184
+ // Ahead/behind
185
+ let localAhead;
186
+ let remoteAhead;
187
+ try {
188
+ const ab = getAheadBehind(remote, branch);
189
+ localAhead = ab.ahead;
190
+ remoteAhead = ab.behind; // getAheadBehind returns { ahead: local, behind: remote }
191
+ }
192
+ catch (error) {
193
+ const msg = error instanceof Error ? error.message : String(error);
194
+ if (/not a git repository/i.test(msg)) {
195
+ return { skipped: true, reason: 'Not in a git repository' };
196
+ }
197
+ return { skipped: true, reason: `Could not compute ahead/behind: ${msg}` };
198
+ }
199
+ const state = deriveState(localAhead, remoteAhead);
200
+ // Only compute drift zone when remote has new commits
201
+ let driftZone = [];
202
+ let entries = [];
203
+ if (remoteAhead > 0) {
204
+ driftZone = getDriftZone(remote, branch);
205
+ const unstagedFiles = getUnstagedTrackedFiles();
206
+ entries = classifyDriftZone(driftZone, registeredFiles, unstagedFiles);
207
+ }
208
+ const registeredInDrift = entries.filter(e => e.registered);
209
+ const unstagedInDrift = entries.filter(e => e.unstaged);
210
+ const rebaseContinueRisk = unstagedInDrift.length > 0;
211
+ const safeToPush = remoteAhead === 0;
212
+ const recommendation = deriveRecommendation(state, registeredInDrift, unstagedInDrift);
213
+ return {
214
+ branch,
215
+ remote: upstreamRef,
216
+ localAhead,
217
+ remoteAhead,
218
+ state,
219
+ driftZone,
220
+ registeredInDrift,
221
+ unstagedInDrift,
222
+ safeToPush,
223
+ rebaseContinueRisk,
224
+ recommendation,
225
+ };
226
+ }
227
+ //# sourceMappingURL=remote-drift.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-drift.js","sourceRoot":"","sources":["../../src/lib/remote-drift.ts"],"names":[],"mappings":"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"}