@vibe-commit/capture 0.6.1 → 0.8.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/README.md +191 -9
  2. package/dist/account_not_here.d.ts +15 -0
  3. package/dist/account_not_here.js +25 -0
  4. package/dist/account_not_here.js.map +1 -0
  5. package/dist/agent_hooks.d.ts +8 -0
  6. package/dist/agent_hooks.js +31 -1
  7. package/dist/agent_hooks.js.map +1 -1
  8. package/dist/agents/claude_code.d.ts +34 -0
  9. package/dist/agents/claude_code.js +141 -8
  10. package/dist/agents/claude_code.js.map +1 -1
  11. package/dist/agents/codex_cli.d.ts +13 -0
  12. package/dist/agents/codex_cli.js +241 -2
  13. package/dist/agents/codex_cli.js.map +1 -1
  14. package/dist/agents/cursor.d.ts +34 -0
  15. package/dist/agents/cursor.js +115 -1
  16. package/dist/agents/cursor.js.map +1 -1
  17. package/dist/agents/session_listing.d.ts +29 -0
  18. package/dist/agents/session_listing.js +49 -0
  19. package/dist/agents/session_listing.js.map +1 -0
  20. package/dist/agents/types.d.ts +118 -8
  21. package/dist/agents/types.js +17 -3
  22. package/dist/agents/types.js.map +1 -1
  23. package/dist/commands/approval_pending.d.ts +9 -0
  24. package/dist/commands/approval_pending.js +23 -0
  25. package/dist/commands/approval_pending.js.map +1 -0
  26. package/dist/commands/auth.d.ts +7 -0
  27. package/dist/commands/auth.js +52 -11
  28. package/dist/commands/auth.js.map +1 -1
  29. package/dist/commands/backfill.d.ts +160 -0
  30. package/dist/commands/backfill.js +748 -0
  31. package/dist/commands/backfill.js.map +1 -0
  32. package/dist/commands/browser_credential.d.ts +6 -2
  33. package/dist/commands/browser_credential.js +34 -14
  34. package/dist/commands/browser_credential.js.map +1 -1
  35. package/dist/commands/connect.d.ts +146 -0
  36. package/dist/commands/connect.js +216 -117
  37. package/dist/commands/connect.js.map +1 -1
  38. package/dist/commands/connect_account.d.ts +135 -0
  39. package/dist/commands/connect_account.js +321 -0
  40. package/dist/commands/connect_account.js.map +1 -0
  41. package/dist/commands/connect_picker.d.ts +27 -0
  42. package/dist/commands/connect_picker.js +549 -0
  43. package/dist/commands/connect_picker.js.map +1 -0
  44. package/dist/commands/context.d.ts +16 -0
  45. package/dist/commands/context.js +27 -0
  46. package/dist/commands/context.js.map +1 -1
  47. package/dist/commands/credential_problem.d.ts +15 -4
  48. package/dist/commands/credential_problem.js +29 -22
  49. package/dist/commands/credential_problem.js.map +1 -1
  50. package/dist/commands/device_credential.d.ts +5 -1
  51. package/dist/commands/device_credential.js +17 -14
  52. package/dist/commands/device_credential.js.map +1 -1
  53. package/dist/commands/finalize.d.ts +95 -0
  54. package/dist/commands/finalize.js +249 -74
  55. package/dist/commands/finalize.js.map +1 -1
  56. package/dist/commands/finish_mint.d.ts +30 -6
  57. package/dist/commands/finish_mint.js +26 -6
  58. package/dist/commands/finish_mint.js.map +1 -1
  59. package/dist/commands/report.js +38 -30
  60. package/dist/commands/report.js.map +1 -1
  61. package/dist/commands/scan.d.ts +162 -0
  62. package/dist/commands/scan.js +507 -0
  63. package/dist/commands/scan.js.map +1 -0
  64. package/dist/commands/status.d.ts +19 -1
  65. package/dist/commands/status.js +232 -26
  66. package/dist/commands/status.js.map +1 -1
  67. package/dist/commands/status_hooks.d.ts +14 -0
  68. package/dist/commands/status_hooks.js +81 -0
  69. package/dist/commands/status_hooks.js.map +1 -0
  70. package/dist/commands/status_machine.d.ts +27 -0
  71. package/dist/commands/status_machine.js +210 -0
  72. package/dist/commands/status_machine.js.map +1 -0
  73. package/dist/commands/sync_reason.d.ts +17 -0
  74. package/dist/commands/sync_reason.js +25 -0
  75. package/dist/commands/sync_reason.js.map +1 -0
  76. package/dist/commands/why.js +44 -31
  77. package/dist/commands/why.js.map +1 -1
  78. package/dist/consent.d.ts +217 -0
  79. package/dist/consent.js +400 -1
  80. package/dist/consent.js.map +1 -1
  81. package/dist/copy/error_codes.d.ts +222 -0
  82. package/dist/copy/error_codes.js +105 -0
  83. package/dist/copy/error_codes.js.map +1 -0
  84. package/dist/copy/index.d.ts +2 -2
  85. package/dist/copy/index.js +2 -2
  86. package/dist/copy/index.js.map +1 -1
  87. package/dist/copy/strings.d.ts +617 -30
  88. package/dist/copy/strings.js +741 -36
  89. package/dist/copy/strings.js.map +1 -1
  90. package/dist/copy/time.d.ts +11 -0
  91. package/dist/copy/time.js +18 -0
  92. package/dist/copy/time.js.map +1 -1
  93. package/dist/credential.d.ts +5 -1
  94. package/dist/credential.js +2 -2
  95. package/dist/credential.js.map +1 -1
  96. package/dist/git.d.ts +43 -0
  97. package/dist/git.js +95 -0
  98. package/dist/git.js.map +1 -1
  99. package/dist/grants_sync.d.ts +165 -0
  100. package/dist/grants_sync.js +289 -0
  101. package/dist/grants_sync.js.map +1 -0
  102. package/dist/grants_verb.d.ts +70 -0
  103. package/dist/grants_verb.js +121 -0
  104. package/dist/grants_verb.js.map +1 -0
  105. package/dist/hooks/entry.d.ts +18 -1
  106. package/dist/hooks/entry.js +117 -14
  107. package/dist/hooks/entry.js.map +1 -1
  108. package/dist/hooks/post_commit.js +3 -3
  109. package/dist/hooks/post_commit.js.map +1 -1
  110. package/dist/hooks/post_rewrite.js +6 -4
  111. package/dist/hooks/post_rewrite.js.map +1 -1
  112. package/dist/hooks/session_grants.d.ts +59 -0
  113. package/dist/hooks/session_grants.js +91 -0
  114. package/dist/hooks/session_grants.js.map +1 -0
  115. package/dist/hooks/session_start.d.ts +114 -0
  116. package/dist/hooks/session_start.js +243 -0
  117. package/dist/hooks/session_start.js.map +1 -0
  118. package/dist/index.d.ts +1 -1
  119. package/dist/index.js +76 -11
  120. package/dist/index.js.map +1 -1
  121. package/dist/install.d.ts +57 -0
  122. package/dist/install.js +54 -20
  123. package/dist/install.js.map +1 -1
  124. package/dist/json.d.ts +32 -9
  125. package/dist/json.js +35 -8
  126. package/dist/json.js.map +1 -1
  127. package/dist/machine_state.d.ts +52 -0
  128. package/dist/machine_state.js +63 -0
  129. package/dist/machine_state.js.map +1 -0
  130. package/dist/oauth/retire.d.ts +10 -0
  131. package/dist/oauth/retire.js +13 -0
  132. package/dist/oauth/retire.js.map +1 -1
  133. package/dist/oauth/session.d.ts +1 -0
  134. package/dist/org_pending.d.ts +52 -0
  135. package/dist/org_pending.js +109 -0
  136. package/dist/org_pending.js.map +1 -0
  137. package/dist/paths.d.ts +70 -0
  138. package/dist/paths.js +90 -0
  139. package/dist/paths.js.map +1 -1
  140. package/dist/pending_revoke.d.ts +117 -0
  141. package/dist/pending_revoke.js +233 -0
  142. package/dist/pending_revoke.js.map +1 -0
  143. package/dist/pending_revoke_file.d.ts +55 -0
  144. package/dist/pending_revoke_file.js +74 -0
  145. package/dist/pending_revoke_file.js.map +1 -0
  146. package/dist/picker.d.ts +208 -0
  147. package/dist/picker.js +526 -0
  148. package/dist/picker.js.map +1 -0
  149. package/dist/picker_checklist.d.ts +141 -0
  150. package/dist/picker_checklist.js +411 -0
  151. package/dist/picker_checklist.js.map +1 -0
  152. package/dist/policy.d.ts +70 -1
  153. package/dist/policy.js +68 -2
  154. package/dist/policy.js.map +1 -1
  155. package/dist/post.d.ts +91 -18
  156. package/dist/post.js +259 -27
  157. package/dist/post.js.map +1 -1
  158. package/dist/state.d.ts +6 -0
  159. package/dist/state.js +38 -1
  160. package/dist/state.js.map +1 -1
  161. package/dist/system_message.d.ts +32 -2
  162. package/dist/system_message.js +47 -5
  163. package/dist/system_message.js.map +1 -1
  164. package/dist/term.d.ts +28 -2
  165. package/dist/term.js +23 -2
  166. package/dist/term.js.map +1 -1
  167. package/dist/verb_help.d.ts +13 -0
  168. package/dist/verb_help.js +40 -0
  169. package/dist/verb_help.js.map +1 -0
  170. package/dist/version.d.ts +1 -1
  171. package/dist/version.js +1 -1
  172. package/package.json +5 -9
@@ -1 +1 @@
1
- {"version":3,"file":"post_rewrite.js","sourceRoot":"","sources":["../../src/hooks/post_rewrite.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"post_rewrite.js","sourceRoot":"","sources":["../../src/hooks/post_rewrite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * `SessionStart`'s one bounded read of the account's grants (slice 2, `CR-259`, S4; exception 2, VT's conditions).
3
+ *
4
+ * ```
5
+ * GET <ingest origin>/ingest/v1/grants 200 { "schema": 1, "epoch", "owners", "repos", "excluded" }
6
+ * ```
7
+ *
8
+ * This is the ONLY place a hook reads a successful response body. It is a separate request from any upload and it never goes through
9
+ * `send`, so an ingest reply's 2xx body is still not read on the hook path (`post.ts`).
10
+ *
11
+ * ## When it runs — all four, or not at all
12
+ *
13
+ * 1. the machine's account state is **stale**: a credential-lane answer carried an `X-Grant-Epoch` that is not the epoch last
14
+ * recorded (`noteGrantEpoch`, called from `deliver`). A machine that has seen the same epoch every turn never asks;
15
+ * 2. the last GET was **more than an hour ago** (`last_get_at`). It is written BEFORE the request, so a server that hangs or a
16
+ * hook that is killed mid-request costs the next hour of sessions nothing;
17
+ * 3. there is a **usable credential and ingest address**;
18
+ * 4. the hook has **budget to spare**: the GET is bounded at 1,000 ms and by what is left of the hook's own wall clock.
19
+ *
20
+ * ## What it can and cannot do
21
+ *
22
+ * - It reads through `readCappedJson` at the **hook path's 64 KiB** (a CLI verb reads 1 MiB; a hook does not). A stalled, cut-off,
23
+ * oversize or off-contract body is "unavailable": **the state stays stale**, nothing throws, and nothing waits past the bound.
24
+ * - It writes `grants-account.json` — `account`, `stale: false`, `last_get_at` — whole and atomically, and NEVER `grants.json`.
25
+ * `refused` is left as it was: a GET is not a sync, only a sync (or this machine's own next 200) says a refusal is over.
26
+ * - It never syncs: no POST, no queue, no `pending`. Whatever the machine has not delivered stays for the next verb.
27
+ * - What it learned admits nothing. `isCaptureAllowed` never reads `account` as a grant.
28
+ *
29
+ * It returns how many of the account's owner grants and repository grants this machine has not named, so the caller can say state 10.
30
+ * `null` means nothing to say.
31
+ */
32
+ import type { IngestCredential } from "../credential.js";
33
+ /** The most one SessionStart GET waits: exception 2's bound, inside the hook's existing budget. */
34
+ export declare const SESSION_GRANTS_GET_MS = 1000;
35
+ /** At most one GET an hour per machine. */
36
+ export declare const SESSION_GRANTS_MIN_INTERVAL_MS: number;
37
+ export interface SessionGrantsDeps {
38
+ readonly env: NodeJS.ProcessEnv;
39
+ readonly home: string;
40
+ readonly credential: IngestCredential;
41
+ /** Injected so a cell can stub the one request. */
42
+ readonly fetch?: typeof fetch;
43
+ readonly now?: () => Date;
44
+ /** What is left of the hook's own budget, in ms. Absent means the GET's own bound is all there is. */
45
+ readonly budgetLeftMs?: () => number;
46
+ }
47
+ export interface GrantsNoticeFacts {
48
+ /** The account's epoch as the GET read it: the key of the once-per-epoch notice. */
49
+ readonly epoch: number;
50
+ /** How many of the account's OWNER grants this machine has not named. */
51
+ readonly owners: number;
52
+ /** How many of the account's REPOSITORY grants this machine has not named (not under a named owner, not turned off). Owners plus repos is at least 1. */
53
+ readonly repos: number;
54
+ }
55
+ /**
56
+ * Do the one bounded GET if it is due, record what it said, and report the unnamed count if there is one to report.
57
+ * **NEVER THROWS.**
58
+ */
59
+ export declare function refreshAccountGrants(deps: SessionGrantsDeps): Promise<GrantsNoticeFacts | null>;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * `SessionStart`'s one bounded read of the account's grants (slice 2, `CR-259`, S4; exception 2, VT's conditions).
3
+ *
4
+ * ```
5
+ * GET <ingest origin>/ingest/v1/grants 200 { "schema": 1, "epoch", "owners", "repos", "excluded" }
6
+ * ```
7
+ *
8
+ * This is the ONLY place a hook reads a successful response body. It is a separate request from any upload and it never goes through
9
+ * `send`, so an ingest reply's 2xx body is still not read on the hook path (`post.ts`).
10
+ *
11
+ * ## When it runs — all four, or not at all
12
+ *
13
+ * 1. the machine's account state is **stale**: a credential-lane answer carried an `X-Grant-Epoch` that is not the epoch last
14
+ * recorded (`noteGrantEpoch`, called from `deliver`). A machine that has seen the same epoch every turn never asks;
15
+ * 2. the last GET was **more than an hour ago** (`last_get_at`). It is written BEFORE the request, so a server that hangs or a
16
+ * hook that is killed mid-request costs the next hour of sessions nothing;
17
+ * 3. there is a **usable credential and ingest address**;
18
+ * 4. the hook has **budget to spare**: the GET is bounded at 1,000 ms and by what is left of the hook's own wall clock.
19
+ *
20
+ * ## What it can and cannot do
21
+ *
22
+ * - It reads through `readCappedJson` at the **hook path's 64 KiB** (a CLI verb reads 1 MiB; a hook does not). A stalled, cut-off,
23
+ * oversize or off-contract body is "unavailable": **the state stays stale**, nothing throws, and nothing waits past the bound.
24
+ * - It writes `grants-account.json` — `account`, `stale: false`, `last_get_at` — whole and atomically, and NEVER `grants.json`.
25
+ * `refused` is left as it was: a GET is not a sync, only a sync (or this machine's own next 200) says a refusal is over.
26
+ * - It never syncs: no POST, no queue, no `pending`. Whatever the machine has not delivered stays for the next verb.
27
+ * - What it learned admits nothing. `isCaptureAllowed` never reads `account` as a grant.
28
+ *
29
+ * It returns how many of the account's owner grants and repository grants this machine has not named, so the caller can say state 10.
30
+ * `null` means nothing to say.
31
+ */
32
+ import { accountNotHere } from "../account_not_here.js";
33
+ import { readGrants, readAccountState, writeAccountState, EMPTY_GRANTS } from "../consent.js";
34
+ import { fetchAccountGrants } from "../grants_sync.js";
35
+ import { readPerClone } from "../machine_state.js";
36
+ import { ingestUrl } from "../post.js";
37
+ /** The most one SessionStart GET waits: exception 2's bound, inside the hook's existing budget. */
38
+ export const SESSION_GRANTS_GET_MS = 1_000;
39
+ /** At most one GET an hour per machine. */
40
+ export const SESSION_GRANTS_MIN_INTERVAL_MS = 60 * 60 * 1000;
41
+ /** Kept back from the hook's wall clock for everything after the request (the notice, the write, the exit). */
42
+ const RESERVE_MS = 300;
43
+ /** Under this the request is not worth starting: the hook just leaves the state stale. */
44
+ const MIN_TIMEOUT_MS = 100;
45
+ /**
46
+ * Do the one bounded GET if it is due, record what it said, and report the unnamed count if there is one to report.
47
+ * **NEVER THROWS.**
48
+ */
49
+ export async function refreshAccountGrants(deps) {
50
+ try {
51
+ const now = (deps.now ?? (() => new Date()))();
52
+ const state = readAccountState(deps.home);
53
+ if (!state.stale)
54
+ return null;
55
+ if (state.last_get_at !== null) {
56
+ const last = Date.parse(state.last_get_at);
57
+ if (Number.isFinite(last) && now.getTime() - last < SESSION_GRANTS_MIN_INTERVAL_MS && now.getTime() >= last)
58
+ return null;
59
+ }
60
+ const url = ingestUrl(deps.env);
61
+ if (url === null)
62
+ return null;
63
+ const left = deps.budgetLeftMs?.() ?? Number.POSITIVE_INFINITY;
64
+ const timeoutMs = Math.min(SESSION_GRANTS_GET_MS, left - RESERVE_MS);
65
+ if (!(timeoutMs >= MIN_TIMEOUT_MS))
66
+ return null;
67
+ // Before the request, not after it: a hang must not be paid for again by every session of the next hour.
68
+ writeAccountState(deps.home, { ...state, last_get_at: now.toISOString() });
69
+ const read = await fetchAccountGrants(url, deps.credential, { fetch: deps.fetch ?? fetch, timeoutMs });
70
+ if (read.kind !== "ok")
71
+ return null;
72
+ const stamp = now.toISOString();
73
+ const account = { owners: read.owners, repos: read.repos, excluded: read.excluded, epoch: read.epoch, synced_at: stamp };
74
+ // Re-read: another hook or a verb may have written the file during the request, and only this hook's own fields are ours to set.
75
+ writeAccountState(deps.home, { ...readAccountState(deps.home), account, stale: false, last_get_at: stamp });
76
+ const grants = readGrants(deps.home);
77
+ if (grants.kind === "unreadable")
78
+ return null;
79
+ // A repo this machine holds only a per-clone consent for is on here: count it as named (the same resolution `status` uses).
80
+ const perClone = readPerClone(deps.home).flatMap((c) => (c.slug === null ? [] : [c.slug]));
81
+ const notHere = accountNotHere(grants.kind === "ok" ? grants.grants : EMPTY_GRANTS, account, perClone);
82
+ // `notHere` names an owner as `owner/` and a repo as its slug (`account_not_here.ts`): the trailing slash is the split.
83
+ const owners = notHere.filter((name) => name.endsWith("/")).length;
84
+ const repos = notHere.length - owners;
85
+ return owners + repos === 0 ? null : { epoch: read.epoch, owners, repos };
86
+ }
87
+ catch {
88
+ return null;
89
+ }
90
+ }
91
+ //# sourceMappingURL=session_grants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session_grants.js","sourceRoot":"","sources":["../../src/hooks/session_grants.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * `SessionStart` — the event that never uploads (0.7.0, eng review D3 · A, D4 · A, A4).
3
+ *
4
+ * It does three things in a clone that is already captured, and one more that asks nothing of the clone:
5
+ *
6
+ * 1. installs the clone's two git hooks, once, and ONLY when that is a plain write;
7
+ * 2. says so, once, as the hook's one `systemMessage` (style guide §10.1 states 6-8);
8
+ * 3. says the other things a session start can know without sending anything: the machine has no
9
+ * credential (state 1), the credential ends soon (state 5), `grants.json` is unreadable (state 9).
10
+ * 4. (slice 2) when the account state is stale and an hour has passed, makes ONE bounded `GET` of the account's grants
11
+ * (`session_grants.ts`) and, if the account grants repositories this machine has not named, says so once per account
12
+ * epoch (state 10). It names no repo and sends nothing about the clone: the request is the machine's credential and a path.
13
+ *
14
+ * ⛔ **IT NEVER READS `transcript_path` AND NEVER UPLOADS.** `entry.ts` resolves the canonical event first and
15
+ * branches here BEFORE the consent gate and before the transcript confinement check, so this module is not a
16
+ * path a transcript can reach. There is no `fetch` call here, and the one request anything it imports can make is
17
+ * `session_grants.ts`'s GET, which runs only on a stale account state, at most hourly (a machine that has never been told a
18
+ * different epoch makes none); the cells in `test/session-start.test.ts` assert 0 requests and an unopened transcript for
19
+ * each of the three dialects.
20
+ *
21
+ * ⚠ **The consent gate is still applied — HERE**, because installing git hooks into a repo is a write into
22
+ * the user's clone and "absence means no" covers writes as much as reads. An ungranted or excluded clone gets
23
+ * silence and no file.
24
+ *
25
+ * ## The budget
26
+ *
27
+ * SessionStart runs on each agent's STOP clocks, with no fast path of its own (eng review D7 · B, Alexander's
28
+ * choice over a 1.5 s cap). That is a logged shortcut — gstack-shortcut(dec-e650afbf) — and the constants carry
29
+ * the marker in `src/agents/*.ts`. The ceiling: a hung git call here can hold a session's start up by as long
30
+ * as the agent's REGISTERED timeout. `startSpawnBudget` (armed in `runHook`) still bounds every spawn.
31
+ */
32
+ import { credentialFingerprint } from "../post.js";
33
+ import { type ProjectKeys } from "../project.js";
34
+ import type { NoticeState } from "../system_message.js";
35
+ /** The slice of `hookBody` this module needs, injected so it carries no import cycle with `entry.ts`. */
36
+ export interface SessionStartContext {
37
+ /**
38
+ * Which agent registered this hook (`--agent=`). Cursor's `sessionStart` has NO field a user sees, so for it the
39
+ * handler installs and returns null: it renders nothing and claims nothing (see `sessionStartPayload`).
40
+ */
41
+ readonly agentId: string;
42
+ readonly env: NodeJS.ProcessEnv;
43
+ readonly home: string;
44
+ /** `process.argv[1]` — the path the git hooks will invoke, and the channel test's input. */
45
+ readonly selfPath: string;
46
+ readonly cwd: string;
47
+ /**
48
+ * Render a state into the hook's stdout payload, or null when it is already claimed, unrenderable or
49
+ * unclaimable. `cloneKey` is passed only by states 6-8. This is `hookBody`'s own `notice` closure.
50
+ */
51
+ readonly notice: (state: NoticeState, repoKey?: string | null, rejected?: Parameters<typeof credentialFingerprint>[0], endsAt?: string, cloneKey?: string,
52
+ /** State 10 only: the account epoch the GET read and how many of its owner and repository grants this machine has not named. */
53
+ account?: {
54
+ readonly epoch: number;
55
+ readonly owners: number;
56
+ readonly repos: number;
57
+ }) => string | null;
58
+ /** What is left of the hook's wall clock, in ms: the one GET is bounded by it as well as by its own 1,000 ms. Absent: no outer bound. */
59
+ readonly budgetLeftMs?: () => number;
60
+ /** Injected so a cell can stub the one request and the clock. */
61
+ readonly fetch?: typeof fetch;
62
+ readonly now?: () => Date;
63
+ }
64
+ /**
65
+ * This clone's identity for the once-per-clone markers: a random nonce in `<common-dir>/capture-clone-id`,
66
+ * written once, on the first install in a granted clone (eng review D4 · A, VQ's ruling on PR 4's P1).
67
+ *
68
+ * ⛔ **WHY A NONCE AND NOT SOMETHING DERIVED FROM GIT.** The first version keyed on the common dir plus the oldest
69
+ * HEAD reflog entry, and that key MOVES: a linked worktree has its own HEAD reflog, `git gc` expires old entries
70
+ * (reachable ones after 90 days, unreachable after 30), and a reflog past about 18k entries overflows the spawn's
71
+ * 1 MiB buffer. Each gave a new key, so a deleted hook was written back — the one thing D4 forbids. A file in the
72
+ * common dir has none of those failure modes: worktrees share it, `gc` leaves it alone, and a fresh clone at the
73
+ * same path has no `.git` of the old one, so it has no id and installs again — D4's three properties, kept.
74
+ *
75
+ * Returns null when the id can be neither read nor made (a read-only `.git`): no key means no install, which is the
76
+ * safe direction. `wx` makes the first writer win; a racing second session reads the winner's value.
77
+ */
78
+ export declare function cloneId(commonDir: string): string | null;
79
+ /**
80
+ * Install this clone's git hooks if, and only if, it is the first time and the write is a plain one.
81
+ *
82
+ * Returns the notice STATE to speak (6, 7 or 8), or null for "nothing to say" — which includes a clone that
83
+ * already had an install record (D4: a hook the user deleted stays deleted; `vibecommit connect` puts it back
84
+ * with the user watching), one whose slots were already ours, and a write that failed.
85
+ *
86
+ * ⭐ **STATE 6 IS OWED UNTIL IT HAS BEEN SAID.** The install record says the hooks were written; whether the
87
+ * notice was SAID is its own once-per-clone claim. So a clone installed in a session where state 1 or 5 outranked
88
+ * 6, or installed by Cursor's `sessionStart` (which says nothing), still owes state 6, and the next hook that can
89
+ * speak says it — until `renderNotice` has claimed it, after which it is never owed again.
90
+ *
91
+ * What is recorded, and what is not: an install, and a clone whose slots were already ours, write the record. A
92
+ * `core.hooksPath` redirect and a foreign hook write no hook and no install record — the clone id IS written (it
93
+ * is a consented repo, and the markers for states 7 and 8 are keyed by it), so those states stay once per clone —
94
+ * and a later session re-probes, cheaply and silently. A `failed` write is retried next session for the same
95
+ * reason.
96
+ */
97
+ export declare function installOnce(ctx: Pick<SessionStartContext, "env" | "home" | "selfPath">, keys: ProjectKeys): {
98
+ readonly state: NoticeState | null;
99
+ readonly cloneKey: string;
100
+ };
101
+ /**
102
+ * The `SessionStart` hook body. Returns the stdout payload or null; never throws past the caller's catch, and
103
+ * opens no transcript.
104
+ *
105
+ * Precedence — one hook speaks at most once: 9, then 10, then 1, then 5, then 7, 8, 6. (States 2 and 4 need a send, and
106
+ * 3 is `hookBody`'s own check ahead of the branch, so on a runtime below the Node floor 3 outranks 9: nothing
107
+ * else on such a runtime works either.) A state that is already claimed returns null and the next one speaks.
108
+ *
109
+ * State 10 needs a usable credential, so it cannot share a session with state 1; it outranks 5 and the three install states.
110
+ * It is the one notice that can speak from a clone THIS machine does not capture — the clone an account grant names is exactly
111
+ * such a clone — so it is gated on the clone having a remote (as state 9 is), not on `isCaptureAllowed`. What it sends is the
112
+ * machine's credential and no word about the clone.
113
+ */
114
+ export declare function sessionStartPayload(ctx: SessionStartContext): Promise<string | null>;
@@ -0,0 +1,243 @@
1
+ /**
2
+ * `SessionStart` — the event that never uploads (0.7.0, eng review D3 · A, D4 · A, A4).
3
+ *
4
+ * It does three things in a clone that is already captured, and one more that asks nothing of the clone:
5
+ *
6
+ * 1. installs the clone's two git hooks, once, and ONLY when that is a plain write;
7
+ * 2. says so, once, as the hook's one `systemMessage` (style guide §10.1 states 6-8);
8
+ * 3. says the other things a session start can know without sending anything: the machine has no
9
+ * credential (state 1), the credential ends soon (state 5), `grants.json` is unreadable (state 9).
10
+ * 4. (slice 2) when the account state is stale and an hour has passed, makes ONE bounded `GET` of the account's grants
11
+ * (`session_grants.ts`) and, if the account grants repositories this machine has not named, says so once per account
12
+ * epoch (state 10). It names no repo and sends nothing about the clone: the request is the machine's credential and a path.
13
+ *
14
+ * ⛔ **IT NEVER READS `transcript_path` AND NEVER UPLOADS.** `entry.ts` resolves the canonical event first and
15
+ * branches here BEFORE the consent gate and before the transcript confinement check, so this module is not a
16
+ * path a transcript can reach. There is no `fetch` call here, and the one request anything it imports can make is
17
+ * `session_grants.ts`'s GET, which runs only on a stale account state, at most hourly (a machine that has never been told a
18
+ * different epoch makes none); the cells in `test/session-start.test.ts` assert 0 requests and an unopened transcript for
19
+ * each of the three dialects.
20
+ *
21
+ * ⚠ **The consent gate is still applied — HERE**, because installing git hooks into a repo is a write into
22
+ * the user's clone and "absence means no" covers writes as much as reads. An ungranted or excluded clone gets
23
+ * silence and no file.
24
+ *
25
+ * ## The budget
26
+ *
27
+ * SessionStart runs on each agent's STOP clocks, with no fast path of its own (eng review D7 · B, Alexander's
28
+ * choice over a 1.5 s cap). That is a logged shortcut — gstack-shortcut(dec-e650afbf) — and the constants carry
29
+ * the marker in `src/agents/*.ts`. The ceiling: a hung git call here can hold a session's start up by as long
30
+ * as the agent's REGISTERED timeout. `startSpawnBudget` (armed in `runHook`) still bounds every spawn.
31
+ */
32
+ import { randomBytes } from "node:crypto";
33
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
34
+ import { dirname, join } from "node:path";
35
+ import { grantsUnreadable, isCaptureAllowed, isLocalSlug, readAccountState } from "../consent.js";
36
+ import { endingSoon, metaFor } from "../credential_meta.js";
37
+ import { loadCredential } from "../credential.js";
38
+ import { onceRepoSlug } from "../git.js";
39
+ import { refreshAccountGrants } from "./session_grants.js";
40
+ import { installChannel, installCaptureHooks } from "../install.js";
41
+ import { cloneMarkerPath } from "../paths.js";
42
+ import { credentialFingerprint } from "../post.js";
43
+ import { resolveProjectKeys } from "../project.js";
44
+ /** The file in the git COMMON dir that names this clone. Shared by every linked worktree; `gc` never touches it. */
45
+ // ⚠ Not `vibecommit-…`: `test/provenance.test.ts` reads every `vibecommit-<word>` token in src/ as a sibling repository
46
+ // that must be declared, so a filename of that shape fails it. The name is a plain one for that reason alone.
47
+ const CLONE_ID_FILE = "capture-clone-id";
48
+ /**
49
+ * This clone's identity for the once-per-clone markers: a random nonce in `<common-dir>/capture-clone-id`,
50
+ * written once, on the first install in a granted clone (eng review D4 · A, VQ's ruling on PR 4's P1).
51
+ *
52
+ * ⛔ **WHY A NONCE AND NOT SOMETHING DERIVED FROM GIT.** The first version keyed on the common dir plus the oldest
53
+ * HEAD reflog entry, and that key MOVES: a linked worktree has its own HEAD reflog, `git gc` expires old entries
54
+ * (reachable ones after 90 days, unreachable after 30), and a reflog past about 18k entries overflows the spawn's
55
+ * 1 MiB buffer. Each gave a new key, so a deleted hook was written back — the one thing D4 forbids. A file in the
56
+ * common dir has none of those failure modes: worktrees share it, `gc` leaves it alone, and a fresh clone at the
57
+ * same path has no `.git` of the old one, so it has no id and installs again — D4's three properties, kept.
58
+ *
59
+ * Returns null when the id can be neither read nor made (a read-only `.git`): no key means no install, which is the
60
+ * safe direction. `wx` makes the first writer win; a racing second session reads the winner's value.
61
+ */
62
+ export function cloneId(commonDir) {
63
+ const path = join(commonDir, CLONE_ID_FILE);
64
+ const read = () => {
65
+ try {
66
+ const text = readFileSync(path, "utf8").trim();
67
+ return /^[0-9a-f]{32}$/.test(text) ? text : null;
68
+ }
69
+ catch {
70
+ return null;
71
+ }
72
+ };
73
+ const existing = read();
74
+ if (existing !== null)
75
+ return existing;
76
+ try {
77
+ writeFileSync(path, `${randomBytes(16).toString("hex")}\n`, { flag: "wx", mode: 0o600 });
78
+ }
79
+ catch {
80
+ // Lost the race (EEXIST) or cannot write; either way the file, if there is one, is the answer.
81
+ }
82
+ return read();
83
+ }
84
+ /** The install record: `clone/<digest>/installed.json`, beside the notice markers. */
85
+ function installRecordPath(home, key) {
86
+ return cloneMarkerPath(home, key, "installed");
87
+ }
88
+ /** What the install record says. `wrote` is whether THIS client put a hook there, which is what owes the clone state 6. */
89
+ function readInstallRecord(home, key) {
90
+ try {
91
+ const parsed = JSON.parse(readFileSync(installRecordPath(home, key), "utf8"));
92
+ return { wrote: parsed.wrote === true };
93
+ }
94
+ catch {
95
+ return null;
96
+ }
97
+ }
98
+ /** Best effort; a record we cannot write means the next session tries again, which is the safe direction. */
99
+ function writeInstallRecord(home, key, wrote) {
100
+ try {
101
+ const path = installRecordPath(home, key);
102
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
103
+ writeFileSync(path, `${JSON.stringify({ at: new Date().toISOString(), wrote })}\n`, { flag: "wx", mode: 0o600 });
104
+ }
105
+ catch {
106
+ // An existing record (`wx`) or an unwritable home: both leave the clone as it was.
107
+ }
108
+ }
109
+ /**
110
+ * Install this clone's git hooks if, and only if, it is the first time and the write is a plain one.
111
+ *
112
+ * Returns the notice STATE to speak (6, 7 or 8), or null for "nothing to say" — which includes a clone that
113
+ * already had an install record (D4: a hook the user deleted stays deleted; `vibecommit connect` puts it back
114
+ * with the user watching), one whose slots were already ours, and a write that failed.
115
+ *
116
+ * ⭐ **STATE 6 IS OWED UNTIL IT HAS BEEN SAID.** The install record says the hooks were written; whether the
117
+ * notice was SAID is its own once-per-clone claim. So a clone installed in a session where state 1 or 5 outranked
118
+ * 6, or installed by Cursor's `sessionStart` (which says nothing), still owes state 6, and the next hook that can
119
+ * speak says it — until `renderNotice` has claimed it, after which it is never owed again.
120
+ *
121
+ * What is recorded, and what is not: an install, and a clone whose slots were already ours, write the record. A
122
+ * `core.hooksPath` redirect and a foreign hook write no hook and no install record — the clone id IS written (it
123
+ * is a consented repo, and the markers for states 7 and 8 are keyed by it), so those states stay once per clone —
124
+ * and a later session re-probes, cheaply and silently. A `failed` write is retried next session for the same
125
+ * reason.
126
+ */
127
+ export function installOnce(ctx, keys) {
128
+ // No binary path to point a git hook at, or the plugin channel — which installs no git hooks, by contract
129
+ // ("the plugin installs no git hooks" stays true; TODOS [173] (a2) is Alexander's call).
130
+ if (ctx.selfPath === "" || installChannel(ctx.env, ctx.selfPath).kind === "plugin") {
131
+ return { state: null, cloneKey: "" };
132
+ }
133
+ const key = cloneId(keys.consent);
134
+ if (key === null)
135
+ return { state: null, cloneKey: "" };
136
+ const record = readInstallRecord(ctx.home, key);
137
+ if (record !== null) {
138
+ const owed = record.wrote && !existsSync(cloneMarkerPath(ctx.home, key, "hooks_added"));
139
+ return { state: owed ? "hooks_added" : null, cloneKey: key };
140
+ }
141
+ const result = installCaptureHooks(keys.worktree, ctx.selfPath, { plainWriteOnly: true });
142
+ const kinds = [result.commit.kind, result.rewrite.kind];
143
+ if (kinds.includes("hooks-path"))
144
+ return { state: "hooks_path_set", cloneKey: key };
145
+ if (kinds.includes("foreign"))
146
+ return { state: "own_commit_hook", cloneKey: key };
147
+ if (kinds.includes("failed"))
148
+ return { state: null, cloneKey: key };
149
+ const wrote = (v) => v.kind === "installed" || v.kind === "chained";
150
+ const didWrite = wrote(result.commit) || wrote(result.rewrite);
151
+ writeInstallRecord(ctx.home, key, didWrite);
152
+ return { state: didWrite ? "hooks_added" : null, cloneKey: key };
153
+ }
154
+ /**
155
+ * The `SessionStart` hook body. Returns the stdout payload or null; never throws past the caller's catch, and
156
+ * opens no transcript.
157
+ *
158
+ * Precedence — one hook speaks at most once: 9, then 10, then 1, then 5, then 7, 8, 6. (States 2 and 4 need a send, and
159
+ * 3 is `hookBody`'s own check ahead of the branch, so on a runtime below the Node floor 3 outranks 9: nothing
160
+ * else on such a runtime works either.) A state that is already claimed returns null and the next one speaks.
161
+ *
162
+ * State 10 needs a usable credential, so it cannot share a session with state 1; it outranks 5 and the three install states.
163
+ * It is the one notice that can speak from a clone THIS machine does not capture — the clone an account grant names is exactly
164
+ * such a clone — so it is gated on the clone having a remote (as state 9 is), not on `isCaptureAllowed`. What it sends is the
165
+ * machine's credential and no word about the clone.
166
+ */
167
+ export async function sessionStartPayload(ctx) {
168
+ const keys = resolveProjectKeys(ctx.cwd);
169
+ if (keys === null)
170
+ return null;
171
+ const slugOf = onceRepoSlug(keys.worktree);
172
+ // ⛔ CURSOR'S `sessionStart` HAS NO USER-VISIBLE FIELD (Open Question 1, static read), so it installs and says
173
+ // NOTHING: it renders no notice and, because `renderNotice` is what claims, it claims none. Rendering here would
174
+ // print a line nobody sees AND use up the clone's state 6 and the machine's once-a-day 9 and 5, leaving Claude
175
+ // Code and Codex quiet. State 6 stays owed (`installOnce`) for the next hook that can speak — Cursor's first
176
+ // `stop`. Ahead of the state-9 branch for the same reason. And it makes no GET: the answer would be a notice nobody sees,
177
+ // and the stale mark stays for a hook that can speak.
178
+ if (ctx.agentId === "cursor") {
179
+ if (isCaptureAllowed(ctx.home, keys, slugOf))
180
+ installOnce(ctx, keys);
181
+ return null;
182
+ }
183
+ // State 9 first. An unreadable `grants.json` denies every repo with a remote, so the hook can say so once a
184
+ // day per machine — but only from a clone it WOULD have captured, so a folder with no remote hears nothing.
185
+ if (grantsUnreadable(ctx.home) && !isLocalSlug(slugOf())) {
186
+ return ctx.notice("grants_unreadable");
187
+ }
188
+ const allowed = isCaptureAllowed(ctx.home, keys, slugOf);
189
+ // The side effect comes before any notice, so a higher-precedence notice never costs the install — and state 6
190
+ // stays OWED to a later session rather than lost (`installOnce`).
191
+ const installed = allowed ? installOnce(ctx, keys) : null;
192
+ // ⛔ A clone this machine does NOT capture may still be where an account grant is named, so it may make the one GET — under VT's five
193
+ // conditions (#89): (1) the request is the bare `GET /ingest/v1/grants` with only the credential, client-version and accept headers;
194
+ // (2) nothing is written into the clone (no clone id, no git config, no hook); (3) no transcript is opened or stat'ed (this module never
195
+ // names `transcript_path`); (4) the conditions are machine-wide — stale, at most hourly across ALL clones, `timeoutMs` ≤ 1,000, 64 KiB,
196
+ // a stalled or oversize answer stays stale; (5) THE SLUG RESOLVES LAZILY: the remote is looked up (a git spawn) only when the account
197
+ // state this machine already holds names at least one owner or repo AND is stale. A machine whose cached account is empty never spawns git
198
+ // for this, and a clone with no remote asks nothing.
199
+ if (!allowed) {
200
+ const cached = readAccountState(ctx.home);
201
+ if (!cached.stale || cached.account === null || (cached.account.owners.length === 0 && cached.account.repos.length === 0))
202
+ return null;
203
+ if (isLocalSlug(slugOf()))
204
+ return null;
205
+ }
206
+ const load = loadCredential({ env: ctx.env, home: ctx.home });
207
+ if (load.kind === "ok") {
208
+ // State 10. The GET is due only when the account state is stale and an hour has passed (`session_grants.ts`).
209
+ const found = await refreshAccountGrants({
210
+ env: ctx.env,
211
+ home: ctx.home,
212
+ credential: load.credential,
213
+ ...(ctx.fetch === undefined ? {} : { fetch: ctx.fetch }),
214
+ ...(ctx.now === undefined ? {} : { now: ctx.now }),
215
+ ...(ctx.budgetLeftMs === undefined ? {} : { budgetLeftMs: ctx.budgetLeftMs }),
216
+ });
217
+ if (found !== null) {
218
+ const unnamed = ctx.notice("account_grants_unnamed", null, undefined, undefined, undefined, found);
219
+ if (unnamed !== null)
220
+ return unnamed;
221
+ }
222
+ }
223
+ // Everything below is about a clone this machine captures. A clone it does not capture is silent, as it always was.
224
+ if (!allowed || installed === null)
225
+ return null;
226
+ if (load.kind !== "ok") {
227
+ const notConnected = ctx.notice("not_connected");
228
+ if (notConnected !== null)
229
+ return notConnected;
230
+ }
231
+ else {
232
+ const endsAt = endingSoon(metaFor(ctx.home, credentialFingerprint(load.credential)), Date.now());
233
+ if (endsAt !== null) {
234
+ const ending = ctx.notice("credential_ending", null, load.credential, endsAt);
235
+ if (ending !== null)
236
+ return ending;
237
+ }
238
+ }
239
+ if (installed.state === null)
240
+ return null;
241
+ return ctx.notice(installed.state, null, undefined, undefined, installed.cloneKey);
242
+ }
243
+ //# sourceMappingURL=session_start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session_start.js","sourceRoot":"","sources":["../../src/hooks/session_start.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { type InvocationMode } from "./exit.js";
3
- declare const VERBS: readonly ["auth", "connect", "status", "off", "why", "report", "finalize"];
3
+ declare const VERBS: readonly ["auth", "connect", "scan", "backfill", "status", "off", "why", "report", "finalize"];
4
4
  export type Verb = (typeof VERBS)[number];
5
5
  export declare function isVerb(value: string): value is Verb;
6
6
  /**