@vibe-commit/capture 0.6.1 → 0.7.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 (143) hide show
  1. package/README.md +80 -5
  2. package/dist/agent_hooks.d.ts +8 -0
  3. package/dist/agent_hooks.js +31 -1
  4. package/dist/agent_hooks.js.map +1 -1
  5. package/dist/agents/claude_code.d.ts +34 -0
  6. package/dist/agents/claude_code.js +141 -8
  7. package/dist/agents/claude_code.js.map +1 -1
  8. package/dist/agents/codex_cli.d.ts +13 -0
  9. package/dist/agents/codex_cli.js +241 -2
  10. package/dist/agents/codex_cli.js.map +1 -1
  11. package/dist/agents/cursor.d.ts +34 -0
  12. package/dist/agents/cursor.js +115 -1
  13. package/dist/agents/cursor.js.map +1 -1
  14. package/dist/agents/session_listing.d.ts +29 -0
  15. package/dist/agents/session_listing.js +49 -0
  16. package/dist/agents/session_listing.js.map +1 -0
  17. package/dist/agents/types.d.ts +118 -8
  18. package/dist/agents/types.js +17 -3
  19. package/dist/agents/types.js.map +1 -1
  20. package/dist/commands/approval_pending.d.ts +9 -0
  21. package/dist/commands/approval_pending.js +23 -0
  22. package/dist/commands/approval_pending.js.map +1 -0
  23. package/dist/commands/auth.js +31 -11
  24. package/dist/commands/auth.js.map +1 -1
  25. package/dist/commands/backfill.d.ts +160 -0
  26. package/dist/commands/backfill.js +748 -0
  27. package/dist/commands/backfill.js.map +1 -0
  28. package/dist/commands/browser_credential.d.ts +2 -0
  29. package/dist/commands/browser_credential.js +31 -14
  30. package/dist/commands/browser_credential.js.map +1 -1
  31. package/dist/commands/connect.d.ts +137 -0
  32. package/dist/commands/connect.js +203 -109
  33. package/dist/commands/connect.js.map +1 -1
  34. package/dist/commands/connect_picker.d.ts +27 -0
  35. package/dist/commands/connect_picker.js +415 -0
  36. package/dist/commands/connect_picker.js.map +1 -0
  37. package/dist/commands/context.d.ts +16 -0
  38. package/dist/commands/context.js +27 -0
  39. package/dist/commands/context.js.map +1 -1
  40. package/dist/commands/credential_problem.d.ts +15 -4
  41. package/dist/commands/credential_problem.js +29 -22
  42. package/dist/commands/credential_problem.js.map +1 -1
  43. package/dist/commands/device_credential.d.ts +2 -0
  44. package/dist/commands/device_credential.js +16 -14
  45. package/dist/commands/device_credential.js.map +1 -1
  46. package/dist/commands/finalize.d.ts +95 -0
  47. package/dist/commands/finalize.js +249 -74
  48. package/dist/commands/finalize.js.map +1 -1
  49. package/dist/commands/finish_mint.d.ts +2 -6
  50. package/dist/commands/finish_mint.js +10 -2
  51. package/dist/commands/finish_mint.js.map +1 -1
  52. package/dist/commands/report.js +38 -30
  53. package/dist/commands/report.js.map +1 -1
  54. package/dist/commands/scan.d.ts +162 -0
  55. package/dist/commands/scan.js +507 -0
  56. package/dist/commands/scan.js.map +1 -0
  57. package/dist/commands/status.js +119 -22
  58. package/dist/commands/status.js.map +1 -1
  59. package/dist/commands/status_hooks.d.ts +14 -0
  60. package/dist/commands/status_hooks.js +81 -0
  61. package/dist/commands/status_hooks.js.map +1 -0
  62. package/dist/commands/status_machine.d.ts +18 -0
  63. package/dist/commands/status_machine.js +149 -0
  64. package/dist/commands/status_machine.js.map +1 -0
  65. package/dist/commands/why.js +44 -31
  66. package/dist/commands/why.js.map +1 -1
  67. package/dist/consent.d.ts +111 -0
  68. package/dist/consent.js +203 -1
  69. package/dist/consent.js.map +1 -1
  70. package/dist/copy/error_codes.d.ts +222 -0
  71. package/dist/copy/error_codes.js +105 -0
  72. package/dist/copy/error_codes.js.map +1 -0
  73. package/dist/copy/index.d.ts +2 -2
  74. package/dist/copy/index.js +2 -2
  75. package/dist/copy/index.js.map +1 -1
  76. package/dist/copy/strings.d.ts +497 -29
  77. package/dist/copy/strings.js +601 -35
  78. package/dist/copy/strings.js.map +1 -1
  79. package/dist/copy/time.d.ts +11 -0
  80. package/dist/copy/time.js +18 -0
  81. package/dist/copy/time.js.map +1 -1
  82. package/dist/credential.d.ts +5 -1
  83. package/dist/credential.js +2 -2
  84. package/dist/credential.js.map +1 -1
  85. package/dist/git.d.ts +43 -0
  86. package/dist/git.js +95 -0
  87. package/dist/git.js.map +1 -1
  88. package/dist/hooks/entry.d.ts +18 -1
  89. package/dist/hooks/entry.js +110 -13
  90. package/dist/hooks/entry.js.map +1 -1
  91. package/dist/hooks/post_commit.js +3 -3
  92. package/dist/hooks/post_commit.js.map +1 -1
  93. package/dist/hooks/post_rewrite.js +6 -4
  94. package/dist/hooks/post_rewrite.js.map +1 -1
  95. package/dist/hooks/session_start.d.ts +93 -0
  96. package/dist/hooks/session_start.js +199 -0
  97. package/dist/hooks/session_start.js.map +1 -0
  98. package/dist/index.d.ts +1 -1
  99. package/dist/index.js +56 -8
  100. package/dist/index.js.map +1 -1
  101. package/dist/install.d.ts +57 -0
  102. package/dist/install.js +54 -20
  103. package/dist/install.js.map +1 -1
  104. package/dist/json.d.ts +32 -9
  105. package/dist/json.js +35 -8
  106. package/dist/json.js.map +1 -1
  107. package/dist/machine_state.d.ts +52 -0
  108. package/dist/machine_state.js +63 -0
  109. package/dist/machine_state.js.map +1 -0
  110. package/dist/oauth/session.d.ts +1 -0
  111. package/dist/org_pending.d.ts +52 -0
  112. package/dist/org_pending.js +109 -0
  113. package/dist/org_pending.js.map +1 -0
  114. package/dist/paths.d.ts +50 -0
  115. package/dist/paths.js +64 -0
  116. package/dist/paths.js.map +1 -1
  117. package/dist/picker.d.ts +180 -0
  118. package/dist/picker.js +477 -0
  119. package/dist/picker.js.map +1 -0
  120. package/dist/picker_checklist.d.ts +125 -0
  121. package/dist/picker_checklist.js +375 -0
  122. package/dist/picker_checklist.js.map +1 -0
  123. package/dist/policy.d.ts +54 -0
  124. package/dist/policy.js +47 -0
  125. package/dist/policy.js.map +1 -1
  126. package/dist/post.d.ts +50 -16
  127. package/dist/post.js +220 -16
  128. package/dist/post.js.map +1 -1
  129. package/dist/state.d.ts +6 -0
  130. package/dist/state.js +38 -1
  131. package/dist/state.js.map +1 -1
  132. package/dist/system_message.d.ts +8 -1
  133. package/dist/system_message.js +19 -1
  134. package/dist/system_message.js.map +1 -1
  135. package/dist/term.d.ts +28 -2
  136. package/dist/term.js +23 -2
  137. package/dist/term.js.map +1 -1
  138. package/dist/verb_help.d.ts +13 -0
  139. package/dist/verb_help.js +40 -0
  140. package/dist/verb_help.js.map +1 -0
  141. package/dist/version.d.ts +1 -1
  142. package/dist/version.js +1 -1
  143. package/package.json +5 -9
@@ -0,0 +1,507 @@
1
+ /**
2
+ * `vibecommit scan` — design review D17 · 11A, D33 · 27A; capture 0.7.0, PR 1.
3
+ *
4
+ * Which repositories on this machine has a coding agent been used in? Read-only,
5
+ * no network, and VibeCommit writes no file. (Opening Codex's index `readOnly` makes
6
+ * SQLite create its own `-wal`/`-shm` journal files beside it when Codex has closed
7
+ * them, as any SQLite reader does — measured, PR 1 F1; the index itself is never
8
+ * written.) It is the engine `connect` will use for its
9
+ * picker (`scanMachine`, exported for it, D1) and a public verb in its own right,
10
+ * so an AI agent can list capturable repos without entering a consent flow.
11
+ *
12
+ * ## ⛔ NO TRANSCRIPT IS EVER OPENED
13
+ *
14
+ * The consent design is that no path opens a transcript of a repo nobody granted,
15
+ * and the thing that decides what to OFFER cannot be the thing that reads them.
16
+ * Every count here comes from a directory entry's name or an `lstat`'s time
17
+ * (`SourceSession`), and Codex's from four index columns. A folder is resolved to
18
+ * a path by walking the FILESYSTEM against the folder's encoded name — never by
19
+ * reading the `cwd` a transcript records, which is analysis (D60 §D6). The one
20
+ * ruled exception to that is backfill's one-field check, after consent, and it is
21
+ * not in this file.
22
+ *
23
+ * ## The walk, and why it can say no
24
+ *
25
+ * Both folder-keyed agents encode a path LOSSILY (`/a/b-c`, `/a/b/c` and `/a/b.c`
26
+ * are one name under Claude Code's rule), so a name is not a path. The engine
27
+ * encodes every directory ENTRY with the dialect's own `encodeProjectPath` and
28
+ * keeps those whose encoding is the name, or a prefix of it that ends at a
29
+ * separator — so the collapsing and trimming of Cursor's rule apply to every
30
+ * candidate, and nothing is assumed. The outcomes, each a different count:
31
+ *
32
+ * - one existing directory → resolved (a repo if it is a git work tree,
33
+ * else counted as a folder that isn't one)
34
+ * - two or more → ambiguous, skipped
35
+ * - none → the folder no longer exists
36
+ * - a hashed (cut) name → cannot be inverted, counted with ambiguous
37
+ * - one, but the agent's own record names a DELETED path that encodes to the
38
+ * same name → ambiguous too (the deleted-sibling case; the `projects` map)
39
+ *
40
+ * ## The walk reads each directory once
41
+ *
42
+ * Folders under one directory (a temp directory holding hundreds of project
43
+ * folders) all walk through it, and the first version re-read and re-encoded it for
44
+ * every one of them: 5.7 s of an 8.1 s scan on a machine with 130 folders. Within one
45
+ * `scanMachine` run each directory is read ONCE and its children indexed by their
46
+ * full encoding, so a step down the tree is a hash lookup on the prefixes of the name
47
+ * that end at a `-`, not a pass over every entry.
48
+ *
49
+ * ## Path reuse
50
+ *
51
+ * A transcript last written BEFORE its clone's first reflog entry predates the
52
+ * clone, so it may belong to a different repo that once lived at that path. It is
53
+ * skipped. A clone with no reflog cannot be tested and is reported instead, as one
54
+ * backfill will skip. ⚠ Git facts and a file time only.
55
+ */
56
+ import { existsSync, realpathSync } from "node:fs";
57
+ import { readEntries } from "../agents/session_listing.js";
58
+ import { DIALECTS } from "../agents/registry.js";
59
+ import { COMMANDS, SCAN, shortDate } from "../copy/index.js";
60
+ import { connectCommandFor } from "../install.js";
61
+ import { renderVerbHelp } from "../verb_help.js";
62
+ import { normalizeSlug } from "../consent.js";
63
+ import { EXIT } from "../exit.js";
64
+ import { firstReflogSeconds, gitProbe, resolveRepoSlug } from "../git.js";
65
+ import { emitJson } from "../json.js";
66
+ import { resolveProjectKeys } from "../project.js";
67
+ import { paint, tildePath, truncatePath, wrap } from "../term.js";
68
+ import { writeLines } from "./context.js";
69
+ /**
70
+ * Finds the existing directories a folder name encodes, memoizing as it goes.
71
+ *
72
+ * ⛔ **Matching is by the dialect's OWN encoder, applied to the whole candidate
73
+ * path.** A directory is a candidate when its path encodes to `name`, and is
74
+ * descended into when that encoding is a proper prefix of `name` followed by the
75
+ * encoded separator `-`. Encoding the whole path (not just the entry) is what
76
+ * makes Cursor's run-collapsing correct across a boundary: `/a/` + `-b` is one
77
+ * dash there, and two under Claude Code's rule.
78
+ *
79
+ * Directories only, and a symlink is not one (`Dirent.isDirectory` is false for
80
+ * it): both agents name the folder from the working directory's REAL path, so a
81
+ * symlinked component can never be part of a name — `/tmp` is `private-tmp`.
82
+ *
83
+ * ## ⚠ Why an index and not a loop over entries
84
+ *
85
+ * A directory's children are keyed by their FULL encoding, once, when it is first
86
+ * read. A step down is then: for each prefix of `name` that ends at a `-` (a handful),
87
+ * look it up. That is exactly the old loop's test (`encoded === name`, or a proper
88
+ * prefix followed by `-`) with the entries pre-bucketed by the answer, so the old
89
+ * cells are its proof. An entry whose encoding is EMPTY (Cursor, a directory named
90
+ * only punctuation) is keyed to its parent's encoding and found through the same
91
+ * lookup; the empty prefix is tried for the root's sake.
92
+ */
93
+ function makeWalk(read) {
94
+ // Two caches, because they have different keys: a directory's entries are one fact however many agents
95
+ // walk it, while the encodings of its children are one per dialect.
96
+ const directories = new Map();
97
+ const directoriesOf = (dir) => {
98
+ let names = directories.get(dir);
99
+ if (names === undefined) {
100
+ names = [];
101
+ try {
102
+ for (const entry of read(dir) ?? [])
103
+ if (entry.isDirectory())
104
+ names.push(entry.name);
105
+ }
106
+ catch {
107
+ // An unreadable directory has no children we can name; the walk goes on.
108
+ }
109
+ directories.set(dir, names);
110
+ }
111
+ return names;
112
+ };
113
+ const indexes = new Map();
114
+ const indexOf = (dir, encode) => {
115
+ let perDir = indexes.get(encode);
116
+ if (perDir === undefined) {
117
+ perDir = new Map();
118
+ indexes.set(encode, perDir);
119
+ }
120
+ let index = perDir.get(dir);
121
+ if (index === undefined) {
122
+ index = new Map();
123
+ for (const name of directoriesOf(dir)) {
124
+ const path = dir === "/" ? `/${name}` : `${dir}/${name}`;
125
+ const key = encode(path);
126
+ const known = index.get(key);
127
+ if (known === undefined)
128
+ index.set(key, [path]);
129
+ else
130
+ known.push(path);
131
+ }
132
+ perDir.set(dir, index);
133
+ }
134
+ return index;
135
+ };
136
+ /** Every existing directory whose encoding is `name`, up to `limit` (2: is there MORE than one?). */
137
+ return (name, encode, limit = 2) => {
138
+ const found = [];
139
+ // The prefixes a parent's encoding can be: everything before a `-`, then the whole name.
140
+ const prefixes = [""];
141
+ for (let i = 1; i < name.length; i += 1)
142
+ if (name[i] === "-")
143
+ prefixes.push(name.slice(0, i));
144
+ prefixes.push(name);
145
+ const visit = (dir) => {
146
+ const index = indexOf(dir, encode);
147
+ for (const prefix of prefixes) {
148
+ for (const path of index.get(prefix) ?? []) {
149
+ if (found.length >= limit)
150
+ return;
151
+ if (prefix === name)
152
+ found.push(path);
153
+ else
154
+ visit(path);
155
+ }
156
+ }
157
+ };
158
+ visit("/");
159
+ return found;
160
+ };
161
+ }
162
+ function resolveFolder(name, source, find, deleted) {
163
+ if (source.isHashed(name))
164
+ return { kind: "ambiguous" };
165
+ const found = find(name, source.encode);
166
+ if (found.length === 0)
167
+ return { kind: "missing" };
168
+ if (found.length > 1)
169
+ return { kind: "ambiguous" };
170
+ // The agent's own record of a path that encodes to this name but is gone: this
171
+ // folder may be that path's, and the one survivor only a look-alike.
172
+ const deletedSibling = (deleted.get(name) ?? []).some((path) => !existsSync(path));
173
+ return deletedSibling ? { kind: "ambiguous" } : { kind: "resolved", dir: found[0] };
174
+ }
175
+ function probeTree(top, commonDir) {
176
+ const hooksPath = gitProbe(top, ["config", "--get", "core.hooksPath"])?.trim() ?? "";
177
+ return {
178
+ top,
179
+ commonDir,
180
+ slug: normalizeSlug(resolveRepoSlug(top)),
181
+ firstReflogSec: firstReflogSeconds(top),
182
+ hooksPath: hooksPath === "" ? null : hooksPath,
183
+ };
184
+ }
185
+ /** The order the agents are shown in, and the keys every count record carries. */
186
+ const AGENT_ORDER = DIALECTS.map((dialect) => dialect.id);
187
+ function emptyAgents() {
188
+ return { "claude-code": 0, "codex-cli": 0, cursor: 0 };
189
+ }
190
+ /**
191
+ * Scan this machine. Pure of ambient state: `home` and `env` arrive as data, so a
192
+ * test drives it against a throwaway HOME and never against the developer's own
193
+ * agent stores.
194
+ */
195
+ export function scanMachine(home, env, deps = {}) {
196
+ const find = makeWalk(deps.readEntries ?? readEntries);
197
+ let ambiguous = 0;
198
+ let missing = 0;
199
+ let nonRepo = 0;
200
+ let unindexed = 0;
201
+ let reused = 0;
202
+ const unreadable = [];
203
+ const placed = [];
204
+ for (const dialect of DIALECTS) {
205
+ const source = dialect.sessionSource(home, env);
206
+ if (source.kind === "unreadable") {
207
+ unreadable.push({ agent: dialect.id, reason: source.reason });
208
+ }
209
+ else if (source.kind === "rows") {
210
+ unindexed += source.unindexed;
211
+ for (const row of source.rows) {
212
+ // The row's `cwd` is a realpath (measured), so it is compared as one.
213
+ let dir;
214
+ try {
215
+ dir = realpathSync(row.cwd);
216
+ }
217
+ catch {
218
+ missing += 1;
219
+ continue;
220
+ }
221
+ placed.push({ agent: dialect.id, session: row.session, dir });
222
+ }
223
+ }
224
+ else {
225
+ // Recorded paths by their encoding, once, so a folder asks "is there a deleted one for me?" by lookup.
226
+ const deleted = new Map();
227
+ for (const path of source.recorded) {
228
+ const key = source.encode(path);
229
+ deleted.set(key, [...(deleted.get(key) ?? []), path]);
230
+ }
231
+ for (const folder of source.folders) {
232
+ const resolution = resolveFolder(folder.name, source, find, deleted);
233
+ if (resolution.kind === "ambiguous")
234
+ ambiguous += folder.sessions.length;
235
+ else if (resolution.kind === "missing")
236
+ missing += folder.sessions.length;
237
+ else {
238
+ for (const session of folder.sessions) {
239
+ placed.push({ agent: dialect.id, session, dir: resolution.dir });
240
+ }
241
+ }
242
+ }
243
+ }
244
+ }
245
+ // A directory that is not inside a git work tree is not a repository, so its sessions are COUNTED
246
+ // and not listed (ruling 5a, "nothing silently dropped"): most of an agent's folders are scratch
247
+ // directories, and a line each would bury the ones that matter.
248
+ const byDir = new Map();
249
+ const byTop = new Map();
250
+ const treeFor = (dir) => {
251
+ if (byDir.has(dir))
252
+ return byDir.get(dir) ?? null;
253
+ const keys = resolveProjectKeys(dir);
254
+ let tree = null;
255
+ if (keys !== null) {
256
+ tree = byTop.get(keys.worktree) ?? probeTree(keys.worktree, keys.consent);
257
+ byTop.set(keys.worktree, tree);
258
+ }
259
+ byDir.set(dir, tree);
260
+ return tree;
261
+ };
262
+ const groups = new Map();
263
+ const noRemoteByCommonDir = new Map();
264
+ const noReflog = new Set();
265
+ for (const { agent, session, dir } of placed) {
266
+ const tree = treeFor(dir);
267
+ if (tree === null) {
268
+ nonRepo += 1;
269
+ continue;
270
+ }
271
+ if (tree.firstReflogSec === null)
272
+ noReflog.add(tree.top);
273
+ else if (Math.floor(session.mtimeMs / 1000) < tree.firstReflogSec) {
274
+ reused += 1;
275
+ continue;
276
+ }
277
+ if (tree.slug.startsWith("local:")) {
278
+ // One entry per repo, not per worktree: the smallest path is the stable pick.
279
+ const known = noRemoteByCommonDir.get(tree.commonDir);
280
+ if (known === undefined || tree.top < known)
281
+ noRemoteByCommonDir.set(tree.commonDir, tree.top);
282
+ continue;
283
+ }
284
+ const at = session.startedMs ?? session.mtimeMs;
285
+ let group = groups.get(tree.slug);
286
+ if (group === undefined) {
287
+ group = {
288
+ slug: tree.slug,
289
+ sessions: 0,
290
+ sinceMs: at,
291
+ latestMs: at,
292
+ agents: emptyAgents(),
293
+ trees: new Map(),
294
+ members: [],
295
+ };
296
+ groups.set(tree.slug, group);
297
+ }
298
+ group.sessions += 1;
299
+ group.sinceMs = Math.min(group.sinceMs, at);
300
+ group.latestMs = Math.max(group.latestMs, at);
301
+ group.agents[agent] += 1;
302
+ group.trees.set(tree.top, tree);
303
+ group.members.push({ agent, session, dir, clone: tree.top, commonDir: tree.commonDir });
304
+ }
305
+ const repos = [...groups.values()]
306
+ .map((group) => ({
307
+ slug: group.slug,
308
+ sessions: group.sessions,
309
+ sinceMs: group.sinceMs,
310
+ latestMs: group.latestMs,
311
+ agents: group.agents,
312
+ clones: [...group.trees.values()]
313
+ .map((tree) => ({ path: tree.top, hooksPath: tree.hooksPath }))
314
+ .sort((a, b) => (a.path < b.path ? -1 : 1)),
315
+ members: group.members,
316
+ }))
317
+ // Most recent session first (the drawn screen), the slug to break a tie so the
318
+ // order is the same on every run.
319
+ .sort((a, b) => b.latestMs - a.latestMs || (a.slug < b.slug ? -1 : 1));
320
+ return {
321
+ repos,
322
+ notListed: {
323
+ noRemote: [...noRemoteByCommonDir.values()].sort(),
324
+ ambiguousSessions: ambiguous,
325
+ missingFolderSessions: missing,
326
+ nonRepoSessions: nonRepo,
327
+ pathReusedSessions: reused,
328
+ noReflogClones: [...noReflog].sort(),
329
+ unindexedSessions: unindexed,
330
+ unreadableAgents: unreadable,
331
+ },
332
+ };
333
+ }
334
+ /** The words in brackets after an unreadable agent. A plain read failure names no cause. */
335
+ const UNREADABLE_CAUSE = {
336
+ "unrecognised index": "unrecognised index",
337
+ "index locked": "index locked",
338
+ unreadable: null,
339
+ };
340
+ /** The `Not listed here:` lines that apply, in the drawn order. Empty when none do. */
341
+ function notListedLines(notListed, home, connectCommand) {
342
+ const lines = [];
343
+ if (notListed.noRemote.length > 0)
344
+ lines.push(SCAN.noRemote(notListed.noRemote.length, connectCommand));
345
+ if (notListed.ambiguousSessions > 0)
346
+ lines.push(SCAN.ambiguous(notListed.ambiguousSessions));
347
+ if (notListed.nonRepoSessions > 0)
348
+ lines.push(SCAN.nonRepo(notListed.nonRepoSessions));
349
+ if (notListed.missingFolderSessions > 0) {
350
+ lines.push(SCAN.missingFolder(notListed.missingFolderSessions));
351
+ }
352
+ if (notListed.pathReusedSessions > 0)
353
+ lines.push(SCAN.pathReused(notListed.pathReusedSessions));
354
+ const clones = notListed.noReflogClones;
355
+ if (clones.length === 1) {
356
+ // Left-cut to leave room for the sentence around it (§13.4); the filename identifies.
357
+ lines.push(SCAN.noReflogOne(truncatePath(tildePath(clones[0], home), 40)));
358
+ }
359
+ else if (clones.length > 1) {
360
+ lines.push(SCAN.noReflogMany(clones.length));
361
+ for (const clone of clones)
362
+ lines.push(` ${truncatePath(tildePath(clone, home), 70)}`);
363
+ }
364
+ if (notListed.unindexedSessions > 0)
365
+ lines.push(SCAN.unindexed(notListed.unindexedSessions));
366
+ for (const { agent, reason } of notListed.unreadableAgents) {
367
+ lines.push(SCAN.unreadable(SCAN.agent[agent], UNREADABLE_CAUSE[reason]));
368
+ }
369
+ return lines;
370
+ }
371
+ /**
372
+ * The picker's subset of the `Not listed here:` lines (§10.12): repos with no remote and their fix, folders that can't be
373
+ * matched to one repo, and an agent whose store couldn't be read. The other five are scan-only (§10.13).
374
+ */
375
+ export function pickerNotListedLines(notListed, connectCommand) {
376
+ const lines = [];
377
+ if (notListed.noRemote.length > 0)
378
+ lines.push(SCAN.noRemote(notListed.noRemote.length, connectCommand));
379
+ if (notListed.ambiguousSessions > 0)
380
+ lines.push(SCAN.ambiguous(notListed.ambiguousSessions));
381
+ for (const { agent, reason } of notListed.unreadableAgents) {
382
+ lines.push(SCAN.unreadable(SCAN.agent[agent], UNREADABLE_CAUSE[reason]));
383
+ }
384
+ return lines;
385
+ }
386
+ /** True when the scan saw no session at all, so no line could be listed: the new-laptop screen (VQ, PR 3 addition). */
387
+ export function sawNoSession(notListed, home) {
388
+ // Only whether a line exists matters here, never its text, so no command is named.
389
+ return notListedLines(notListed, home, "").length === 0;
390
+ }
391
+ /** The widest a repo name may be before its counts move to a line of their own. */
392
+ const COLUMN_GAP = 3;
393
+ const ROW_INDENT = 2;
394
+ const SECOND_LINE_INDENT = 4;
395
+ /**
396
+ * The screen, as lines. `nowMs` is an argument (`shortDate` needs it) so a golden
397
+ * file pins the clock instead of reading it.
398
+ *
399
+ * SGR roles are the picker table's (D24): `strong` the `Found` line, `text` the
400
+ * repo names and the closing command, `muted` counts, dates, the agent line and the
401
+ * whole `Not listed here:` block. `NO_COLOR` is therefore this output minus the
402
+ * escapes — bold carries the structure and indentation the rest (§13.1).
403
+ */
404
+ export function renderScan(result,
405
+ /** `connectCommand` is this install's `connect` (`connectCommandFor`); absent means the CLI's own name. */
406
+ options) {
407
+ const { colour, home, nowMs } = options;
408
+ const connectCommand = options.connectCommand ?? COMMANDS.connect;
409
+ const lines = [""];
410
+ const listed = notListedLines(result.notListed, home, connectCommand);
411
+ const block = () => listed.length === 0
412
+ ? []
413
+ : [
414
+ "",
415
+ paint(colour, "muted", ` ${SCAN.notListed}`),
416
+ ...listed.map((line) => paint(colour, "muted", ` ${line}`)),
417
+ ];
418
+ if (result.repos.length === 0) {
419
+ lines.push(...wrap(listed.length === 0 ? SCAN.none : SCAN.noneListable, ROW_INDENT).map((line) => paint(colour, "strong", line)), ...block(), "", ` ${SCAN.noneNext} ${connectCommand}`);
420
+ return lines;
421
+ }
422
+ lines.push(...wrap(SCAN.found(result.repos.length), ROW_INDENT).map((line) => paint(colour, "strong", line)), "");
423
+ const counts = (repo) => `${SCAN.sessions(repo.sessions)} · ${SCAN.since(shortDate(repo.sinceMs, nowMs))}`;
424
+ // The name column is as wide as the widest name whose counts still fit in 80
425
+ // columns. A longer name is never cut ("full names, no cap"): its counts drop to
426
+ // the line below instead.
427
+ const fits = (repo, width) => ROW_INDENT + width + COLUMN_GAP + counts(repo).length <= 80;
428
+ const column = result.repos
429
+ .filter((repo) => fits(repo, repo.slug.length))
430
+ .reduce((widest, repo) => Math.max(widest, repo.slug.length), 0);
431
+ for (const repo of result.repos) {
432
+ if (repo.slug.length <= column) {
433
+ lines.push(` ${paint(colour, "text", repo.slug.padEnd(column))}${" ".repeat(COLUMN_GAP)}${paint(colour, "muted", counts(repo))}`);
434
+ }
435
+ else {
436
+ lines.push(` ${paint(colour, "text", repo.slug)}`, `${" ".repeat(SECOND_LINE_INDENT)}${paint(colour, "muted", counts(repo))}`);
437
+ }
438
+ const agents = AGENT_ORDER.filter((agent) => repo.agents[agent] > 0).map((agent) => `${SCAN.agent[agent]} ${repo.agents[agent]}`);
439
+ lines.push(`${" ".repeat(SECOND_LINE_INDENT)}${paint(colour, "muted", agents.join(" · "))}`);
440
+ }
441
+ lines.push(...block(), "", ` ${SCAN.next} ${connectCommand}`);
442
+ return lines;
443
+ }
444
+ /** The `--json` document body — a contract, pinned in `test/json-read-verbs.test.ts`. */
445
+ export function scanDocument(result) {
446
+ return {
447
+ repos: result.repos.map((repo) => ({
448
+ slug: repo.slug,
449
+ sessions: repo.sessions,
450
+ since: new Date(repo.sinceMs).toISOString().slice(0, 10),
451
+ agents: { ...repo.agents },
452
+ clones: repo.clones.map((clone) => clone.path),
453
+ })),
454
+ not_listed: {
455
+ no_remote: result.notListed.noRemote,
456
+ ambiguous_sessions: result.notListed.ambiguousSessions,
457
+ missing_folder_sessions: result.notListed.missingFolderSessions,
458
+ non_repo_sessions: result.notListed.nonRepoSessions,
459
+ path_reused_sessions: result.notListed.pathReusedSessions,
460
+ no_reflog_clones: result.notListed.noReflogClones,
461
+ unindexed_sessions: result.notListed.unindexedSessions,
462
+ unreadable_agents: result.notListed.unreadableAgents.map(({ agent, reason }) => ({
463
+ agent,
464
+ reason,
465
+ })),
466
+ },
467
+ };
468
+ }
469
+ /**
470
+ * `vibecommit scan [--json]`. Exit `0` when a repository was listed, `4` when
471
+ * none was — and `4` is "nothing to report", not an error (DESIGN.md §13.7), so a
472
+ * wrapper can branch on it without parsing copy. It holds even when `Not listed
473
+ * here:` has lines.
474
+ */
475
+ export function scan(ctx, argv = [], deps = {}) {
476
+ // Check-first, like every other verb's `--help`: reads and writes nothing.
477
+ if (argv.includes("--help") || argv.includes("-h")) {
478
+ const helpVerb = "scan"; // an identifier, not a literal, at the writer: `copy-inline-literals` follows argument positions
479
+ writeLines(ctx.stdout, renderVerbHelp(helpVerb));
480
+ return EXIT.ok;
481
+ }
482
+ const json = argv.includes("--json");
483
+ // The beat is one STATIC line, overwritten once with `done` on a terminal (D17);
484
+ // with no terminal or `NO_COLOR` it prints plainly, once, with no overwrite. No
485
+ // spinner (§13.8). `ctx.colour` is false in exactly those cases, and under
486
+ // `--json`, where there is no beat at all.
487
+ const overwrite = ctx.colour && !json;
488
+ const beat = ` ${SCAN.beat}`;
489
+ if (overwrite)
490
+ ctx.stdout.write(`\n${beat}`);
491
+ const result = (deps.scanMachine ?? scanMachine)(ctx.home, ctx.env);
492
+ const code = result.repos.length > 0 ? EXIT.ok : EXIT.empty;
493
+ if (json) {
494
+ emitJson(ctx.stdout, "scan", result.repos.length > 0 ? "found" : "none", scanDocument(result));
495
+ return code;
496
+ }
497
+ const done = `${beat} ${SCAN.beatDone}`;
498
+ ctx.stdout.write(overwrite ? `\r${done}\n` : `\n${done}\n`);
499
+ writeLines(ctx.stdout, renderScan(result, {
500
+ colour: ctx.colour,
501
+ home: ctx.home,
502
+ nowMs: ctx.now().getTime(),
503
+ connectCommand: connectCommandFor(ctx.env, ctx.selfPath),
504
+ }));
505
+ return code;
506
+ }
507
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"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"}