@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
package/dist/policy.d.ts CHANGED
@@ -62,7 +62,22 @@ export declare const NETWORK_CLASS: FailureClass;
62
62
  export declare const DEFAULT_CLASS: FailureClass;
63
63
  /** Classify one HTTP status. `2xx` is the only success. */
64
64
  export declare function classifyStatus(status: number): Disposition;
65
- /** Classify one attempt, response or not. */
65
+ /**
66
+ * The wire code for "the user turned this repository off, on their account" (slice 2, `CR-259`). A cross-repo contract, like
67
+ * `CAPTURE_NOT_APPROVED`: the server answers `403 { error: "repository_excluded" }` to a credential that has synced its
68
+ * grants. Its sibling `repository_not_granted` is ALSO a 403 and is `later` — nothing here names it, because the 403 row
69
+ * above already says so and a code we did not need to name is one fewer that can drift.
70
+ */
71
+ export declare const REPOSITORY_EXCLUDED = "repository_excluded";
72
+ /**
73
+ * Classify one attempt, response or not.
74
+ *
75
+ * ⛔ **ONE 403 IS `never`, AND IT IS IDENTIFIED BY THE ERROR CODE ALONE** (`ErrorDetail.code` is the only thing a caller may
76
+ * branch on, `post.ts`) — and only on a 403. `never` drops bytes, so every doubt is `later`: a 403 with no body, a body that
77
+ * did not parse or was cut off, a code this client does not know, and the same code on any other status all fall through
78
+ * to the 403 row. Excluded means the user said not to capture this repo, so its bytes are not held for a "later" that the
79
+ * user has already refused.
80
+ */
66
81
  export declare function classify(outcome: SendOutcome): Disposition;
67
82
  /**
68
83
  * The §13.6 copy for a class.
@@ -161,6 +176,60 @@ export interface BacklogCaps {
161
176
  * for the tests, which have to reach a boundary they cannot otherwise reach.
162
177
  */
163
178
  export declare function resolveCaps(env: NodeJS.ProcessEnv): BacklogCaps;
179
+ /**
180
+ * The most RAW transcript bytes one delta carries. The server's own ceiling is 16 MiB decompressed
181
+ * (`MAX_DELTA_BYTES`, `ingest_session.ts:146`); half of it leaves room for redaction markers and for a record that
182
+ * straddles the cut.
183
+ */
184
+ export declare const MAX_DELTA_RAW_BYTES: number;
185
+ /**
186
+ * The most COMPRESSED bytes one delta's frame may be. The server refuses a request body over 1 MiB (`MAX_BODY_BYTES`,
187
+ * `src/transport/server.ts:115`, a 413); 960 KiB leaves the rest for the framing the body does not include.
188
+ */
189
+ export declare const MAX_DELTA_FRAME_BYTES: number;
190
+ /**
191
+ * Where a transcript's records end. A boundary is an offset `b` where byte `b - 1` is `\n`.
192
+ *
193
+ * ⛔ A delta must END ON ONE. The server drops a delta's trailing partial line: it counts as `malformed` and is not
194
+ * carried into the next POST (`ingest_session.ts`, `parseNdjsonRecords`' "KNOWN GAP"), so a cut mid-line loses that
195
+ * record for good.
196
+ *
197
+ * Implemented by the caller (`hooks/entry.ts`'s `recordCutter`), because this module is pure and reads no file. An
198
+ * implementation reads bytes only to find a newline; none of them leaves the process.
199
+ */
200
+ export interface RecordCutter {
201
+ /** The largest boundary `b` with `from < b <= limit`, or `null` when there is no newline in `[from, limit)`. */
202
+ readonly lastBoundary: (from: number, limit: number) => number | null;
203
+ /** The first boundary after `from` (the end of the record that starts there), or `null` when none before EOF. */
204
+ readonly firstBoundary: (from: number) => number | null;
205
+ }
206
+ /** What the next delta at `from` should be. `to` is exclusive. */
207
+ export type ChunkPlan = {
208
+ readonly kind: "span";
209
+ readonly to: number;
210
+ }
211
+ /** The record at `from` alone is longer than `maxRaw`: skip `[from, to)` and count it. */
212
+ | {
213
+ readonly kind: "oversize";
214
+ readonly to: number;
215
+ }
216
+ /** The record at `from` is longer than `maxRaw` AND unterminated at EOF. It may still be growing: leave it. */
217
+ | {
218
+ readonly kind: "wait";
219
+ };
220
+ /**
221
+ * Cut the next delta from `from`: everything to `eof` when it fits, else up to the last record boundary inside `maxRaw`.
222
+ *
223
+ * Pure; the cutter is the only thing that touches a file.
224
+ */
225
+ export declare function planChunk(cutter: RecordCutter, from: number, eof: number, maxRaw?: number): ChunkPlan;
226
+ /**
227
+ * Where to cut `[from, to)` in two, at a record boundary, or `null` when the span is a single record and cannot be.
228
+ *
229
+ * Halves by bytes, snapping back to the last boundary at or before the middle. When the first record is longer than
230
+ * half, the cut is that record's end, so the oversize record goes out alone and a second 413 on it is final.
231
+ */
232
+ export declare function splitPoint(cutter: RecordCutter, from: number, to: number): number | null;
164
233
  /** Undelivered bytes currently held. */
165
234
  export declare function pendingBytes(state: FileState): number;
166
235
  /**
package/dist/policy.js CHANGED
@@ -55,6 +55,11 @@ export const STATUS_CLASSES = new Map([
55
55
  // Org approval pending (D60 §D12). Capture has not stopped; it is waiting.
56
56
  [403, "later"],
57
57
  // Payload too large. Retrying the same bytes cannot work.
58
+ //
59
+ // ⚠ PR 4a: this row is now the verdict on a span that CANNOT BE SPLIT — a single record that alone exceeds a limit.
60
+ // `deliver()` halves a splittable span at a record boundary and sends the two halves, which are different bytes, so the
61
+ // reason above still holds for what reaches this table. Only a `deliver()` given no `RecordCutter` (a caller that
62
+ // cannot align) classifies a 413 here directly, and it is `never` there exactly as before.
58
63
  [413, "never"],
59
64
  // Rate limited. The definition of transient.
60
65
  [429, "later"],
@@ -79,9 +84,28 @@ export function classifyStatus(status) {
79
84
  return SERVER_ERROR_CLASS;
80
85
  return DEFAULT_CLASS;
81
86
  }
82
- /** Classify one attempt, response or not. */
87
+ /**
88
+ * The wire code for "the user turned this repository off, on their account" (slice 2, `CR-259`). A cross-repo contract, like
89
+ * `CAPTURE_NOT_APPROVED`: the server answers `403 { error: "repository_excluded" }` to a credential that has synced its
90
+ * grants. Its sibling `repository_not_granted` is ALSO a 403 and is `later` — nothing here names it, because the 403 row
91
+ * above already says so and a code we did not need to name is one fewer that can drift.
92
+ */
93
+ export const REPOSITORY_EXCLUDED = "repository_excluded";
94
+ /**
95
+ * Classify one attempt, response or not.
96
+ *
97
+ * ⛔ **ONE 403 IS `never`, AND IT IS IDENTIFIED BY THE ERROR CODE ALONE** (`ErrorDetail.code` is the only thing a caller may
98
+ * branch on, `post.ts`) — and only on a 403. `never` drops bytes, so every doubt is `later`: a 403 with no body, a body that
99
+ * did not parse or was cut off, a code this client does not know, and the same code on any other status all fall through
100
+ * to the 403 row. Excluded means the user said not to capture this repo, so its bytes are not held for a "later" that the
101
+ * user has already refused.
102
+ */
83
103
  export function classify(outcome) {
84
- return outcome.kind === "unreachable" ? NETWORK_CLASS : classifyStatus(outcome.status);
104
+ if (outcome.kind === "unreachable")
105
+ return NETWORK_CLASS;
106
+ if (outcome.status === 403 && outcome.detail?.code === REPOSITORY_EXCLUDED)
107
+ return "never";
108
+ return classifyStatus(outcome.status);
85
109
  }
86
110
  /**
87
111
  * The §13.6 copy for a class.
@@ -150,6 +174,48 @@ function positiveOr(raw, fallback) {
150
174
  const parsed = Number(raw);
151
175
  return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
152
176
  }
177
+ // ---------------------------------------------------------------------------
178
+ // Delta sizing — PR 4a. One request carries one DELTA, never the whole span to EOF.
179
+ // ---------------------------------------------------------------------------
180
+ /**
181
+ * The most RAW transcript bytes one delta carries. The server's own ceiling is 16 MiB decompressed
182
+ * (`MAX_DELTA_BYTES`, `ingest_session.ts:146`); half of it leaves room for redaction markers and for a record that
183
+ * straddles the cut.
184
+ */
185
+ export const MAX_DELTA_RAW_BYTES = 8 * 1024 * 1024;
186
+ /**
187
+ * The most COMPRESSED bytes one delta's frame may be. The server refuses a request body over 1 MiB (`MAX_BODY_BYTES`,
188
+ * `src/transport/server.ts:115`, a 413); 960 KiB leaves the rest for the framing the body does not include.
189
+ */
190
+ export const MAX_DELTA_FRAME_BYTES = 960 * 1024;
191
+ /**
192
+ * Cut the next delta from `from`: everything to `eof` when it fits, else up to the last record boundary inside `maxRaw`.
193
+ *
194
+ * Pure; the cutter is the only thing that touches a file.
195
+ */
196
+ export function planChunk(cutter, from, eof, maxRaw = MAX_DELTA_RAW_BYTES) {
197
+ if (eof - from <= maxRaw)
198
+ return { kind: "span", to: eof };
199
+ const boundary = cutter.lastBoundary(from, from + maxRaw);
200
+ if (boundary !== null)
201
+ return { kind: "span", to: boundary };
202
+ const end = cutter.firstBoundary(from);
203
+ return end === null ? { kind: "wait" } : { kind: "oversize", to: end };
204
+ }
205
+ /**
206
+ * Where to cut `[from, to)` in two, at a record boundary, or `null` when the span is a single record and cannot be.
207
+ *
208
+ * Halves by bytes, snapping back to the last boundary at or before the middle. When the first record is longer than
209
+ * half, the cut is that record's end, so the oversize record goes out alone and a second 413 on it is final.
210
+ */
211
+ export function splitPoint(cutter, from, to) {
212
+ const middle = from + Math.floor((to - from) / 2);
213
+ const boundary = cutter.lastBoundary(from, middle);
214
+ if (boundary !== null)
215
+ return boundary;
216
+ const end = cutter.firstBoundary(from);
217
+ return end !== null && end < to ? end : null;
218
+ }
153
219
  /** Undelivered bytes currently held. */
154
220
  export function pendingBytes(state) {
155
221
  if (state.backlog.length === 0)
@@ -1 +1 @@
1
- {"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAQzC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,cAAc,GAAsC,IAAI,GAAG,CAAC;IACvE,gFAAgF;IAChF,CAAC,GAAG,EAAE,OAAO,CAAC;IACd,uEAAuE;IACvE,CAAC,GAAG,EAAE,OAAO,CAAC;IACd,2EAA2E;IAC3E,CAAC,GAAG,EAAE,OAAO,CAAC;IACd,0DAA0D;IAC1D,CAAC,GAAG,EAAE,OAAO,CAAC;IACd,6CAA6C;IAC7C,CAAC,GAAG,EAAE,OAAO,CAAC;CACf,CAAC,CAAC;AAEH,uDAAuD;AACvD,MAAM,CAAC,MAAM,kBAAkB,GAAiB,OAAO,CAAC;AAExD,kEAAkE;AAClE,MAAM,CAAC,MAAM,aAAa,GAAiB,OAAO,CAAC;AAEnD;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAiB,OAAO,CAAC;AAEnD,2DAA2D;AAC3D,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG;QAAE,OAAO,IAAI,CAAC;IAC/C,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACtC,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG;QAAE,OAAO,kBAAkB,CAAC;IAC7D,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,QAAQ,CAAC,OAAoB;IAC3C,OAAO,OAAO,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AACzF,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,GAAiB;IAC3C,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,OAAO;YACV,OAAO,MAAM,CAAC,YAAY,CAAC;QAC7B,KAAK,OAAO;YACV,OAAO,MAAM,CAAC,YAAY,CAAC;QAC7B,KAAK,OAAO;YACV,OAAO,MAAM,CAAC,SAAS,CAAC;IAC5B,CAAC;AACH,CAAC;AA6DD,MAAM,CAAC,MAAM,gBAAgB,GAAc;IACzC,UAAU,EAAE,CAAC;IACb,OAAO,EAAE,EAAE;IACX,QAAQ,EAAE,CAAC;IACX,QAAQ,EAAE,CAAC;IACX,UAAU,EAAE,CAAC;IACb,IAAI,EAAE,KAAK;CACZ,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,KAAK,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI;IACtB,KAAK,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI;IAC1B,OAAO,EAAE,GAAG;CACJ,CAAC;AAQX;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,GAAsB;IAChD,OAAO;QACL,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,4BAA4B,EAAE,YAAY,CAAC,KAAK,CAAC;QACvE,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,6BAA6B,EAAE,YAAY,CAAC,KAAK,CAAC;QACxE,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC,8BAA8B,EAAE,YAAY,CAAC,OAAO,CAAC;KAC9E,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,GAAuB,EAAE,QAAgB;IAC3D,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACvC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;AACnE,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,YAAY,CAAC,KAAgB;IAC3C,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACzC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAgB,EAAE,GAAW;IACpD,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC;IAC3D,OAAO,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,KAAgB,EAAE,EAAU,EAAE,KAAa;IACvE,OAAO,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;AACtE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,KAAgB,EAAE,IAAY,EAAE,EAAU;IACpE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;IACvC,OAAO;QACL,6EAA6E;QAC7E,qDAAqD;QACrD,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,UAAU,EAAE,EAAE;QACd,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,KAAK,CAAC,QAAQ,GAAG,OAAO;QAClC,QAAQ,EAAE,KAAK,CAAC,QAAQ,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAChD,6EAA6E;QAC7E,2EAA2E;QAC3E,qEAAqE;QACrE,yBAAyB;QACzB,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CACtB,KAAgB,EAChB,IAAkC,EAClC,KAAa,EACb,IAAiB;IAEjB,MAAM,IAAI,GACR,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC,IAAI;QAC5B,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,0EAA0E;YAC1E,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAEvD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,IAAI,EAAE,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC;IAC3C,MAAM,OAAO,GACX,IAAI,CAAC,EAAE,GAAG,MAAM;QACd,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;QAC7D,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;IAEnB,OAAO,WAAW,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;AACxD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,KAAgB,EAAE,KAAa,EAAE,IAAiB;IAC5E,IAAI,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;IAClC,IAAI,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC5B,IAAI,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;IAC9B,IAAI,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;IAE9B,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QAC1B,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;QAChF,MAAM,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QAC/C,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAClD,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,IAAI,CAAC,WAAW;YAAE,MAAM;QAElD,UAAU,GAAG,MAAM,CAAC,EAAE,CAAC;QACvB,QAAQ,IAAI,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC;QACpC,QAAQ,IAAI,CAAC,CAAC;QACd,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;AACrG,CAAC"}
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAQzC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,cAAc,GAAsC,IAAI,GAAG,CAAC;IACvE,gFAAgF;IAChF,CAAC,GAAG,EAAE,OAAO,CAAC;IACd,uEAAuE;IACvE,CAAC,GAAG,EAAE,OAAO,CAAC;IACd,2EAA2E;IAC3E,CAAC,GAAG,EAAE,OAAO,CAAC;IACd,0DAA0D;IAC1D,EAAE;IACF,oHAAoH;IACpH,wHAAwH;IACxH,kHAAkH;IAClH,2FAA2F;IAC3F,CAAC,GAAG,EAAE,OAAO,CAAC;IACd,6CAA6C;IAC7C,CAAC,GAAG,EAAE,OAAO,CAAC;CACf,CAAC,CAAC;AAEH,uDAAuD;AACvD,MAAM,CAAC,MAAM,kBAAkB,GAAiB,OAAO,CAAC;AAExD,kEAAkE;AAClE,MAAM,CAAC,MAAM,aAAa,GAAiB,OAAO,CAAC;AAEnD;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAiB,OAAO,CAAC;AAEnD,2DAA2D;AAC3D,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG;QAAE,OAAO,IAAI,CAAC;IAC/C,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACtC,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG;QAAE,OAAO,kBAAkB,CAAC;IAC7D,OAAO,aAAa,CAAC;AACvB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,qBAAqB,CAAC;AAEzD;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAoB;IAC3C,IAAI,OAAO,CAAC,IAAI,KAAK,aAAa;QAAE,OAAO,aAAa,CAAC;IACzD,IAAI,OAAO,CAAC,MAAM,KAAK,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,IAAI,KAAK,mBAAmB;QAAE,OAAO,OAAO,CAAC;IAC3F,OAAO,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,GAAiB;IAC3C,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,OAAO;YACV,OAAO,MAAM,CAAC,YAAY,CAAC;QAC7B,KAAK,OAAO;YACV,OAAO,MAAM,CAAC,YAAY,CAAC;QAC7B,KAAK,OAAO;YACV,OAAO,MAAM,CAAC,SAAS,CAAC;IAC5B,CAAC;AACH,CAAC;AA6DD,MAAM,CAAC,MAAM,gBAAgB,GAAc;IACzC,UAAU,EAAE,CAAC;IACb,OAAO,EAAE,EAAE;IACX,QAAQ,EAAE,CAAC;IACX,QAAQ,EAAE,CAAC;IACX,UAAU,EAAE,CAAC;IACb,IAAI,EAAE,KAAK;CACZ,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,KAAK,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI;IACtB,KAAK,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI;IAC1B,OAAO,EAAE,GAAG;CACJ,CAAC;AAQX;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,GAAsB;IAChD,OAAO;QACL,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,4BAA4B,EAAE,YAAY,CAAC,KAAK,CAAC;QACvE,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,6BAA6B,EAAE,YAAY,CAAC,KAAK,CAAC;QACxE,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC,8BAA8B,EAAE,YAAY,CAAC,OAAO,CAAC;KAC9E,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,GAAuB,EAAE,QAAgB;IAC3D,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACvC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;AACnE,CAAC;AAED,8EAA8E;AAC9E,oFAAoF;AACpF,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAEnD;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,GAAG,IAAI,CAAC;AA2BhD;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,MAAoB,EAAE,IAAY,EAAE,GAAW,EAAE,MAAM,GAAG,mBAAmB;IACrG,IAAI,GAAG,GAAG,IAAI,IAAI,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC;IAC3D,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAAC,CAAC;IAC1D,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC;IAC7D,MAAM,GAAG,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC;AACzE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,MAAoB,EAAE,IAAY,EAAE,EAAU;IACvE,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnD,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,QAAQ,CAAC;IACvC,MAAM,GAAG,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO,GAAG,KAAK,IAAI,IAAI,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/C,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,YAAY,CAAC,KAAgB;IAC3C,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACzC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAgB,EAAE,GAAW;IACpD,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC;IAC3D,OAAO,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,KAAgB,EAAE,EAAU,EAAE,KAAa;IACvE,OAAO,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;AACtE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,KAAgB,EAAE,IAAY,EAAE,EAAU;IACpE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;IACvC,OAAO;QACL,6EAA6E;QAC7E,qDAAqD;QACrD,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,UAAU,EAAE,EAAE;QACd,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,KAAK,CAAC,QAAQ,GAAG,OAAO;QAClC,QAAQ,EAAE,KAAK,CAAC,QAAQ,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAChD,6EAA6E;QAC7E,2EAA2E;QAC3E,qEAAqE;QACrE,yBAAyB;QACzB,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CACtB,KAAgB,EAChB,IAAkC,EAClC,KAAa,EACb,IAAiB;IAEjB,MAAM,IAAI,GACR,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC,IAAI;QAC5B,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,0EAA0E;YAC1E,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAEvD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,IAAI,EAAE,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC;IAC3C,MAAM,OAAO,GACX,IAAI,CAAC,EAAE,GAAG,MAAM;QACd,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;QAC7D,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;IAEnB,OAAO,WAAW,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;AACxD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,KAAgB,EAAE,KAAa,EAAE,IAAiB;IAC5E,IAAI,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;IAClC,IAAI,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC5B,IAAI,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;IAC9B,IAAI,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;IAE9B,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QAC1B,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;QAChF,MAAM,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QAC/C,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAClD,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,IAAI,CAAC,WAAW;YAAE,MAAM;QAElD,UAAU,GAAG,MAAM,CAAC,EAAE,CAAC;QACvB,QAAQ,IAAI,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC;QACpC,QAAQ,IAAI,CAAC,CAAC;QACd,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;AACrG,CAAC"}
package/dist/post.d.ts CHANGED
@@ -19,7 +19,7 @@
19
19
  */
20
20
  import { type SelectedAgentId } from "./agents/types.js";
21
21
  import type { IngestCredential } from "./credential.js";
22
- import { type Disposition } from "./policy.js";
22
+ import { type Disposition, type RecordCutter } from "./policy.js";
23
23
  import { type InferredGroupId, type Observed } from "./spool.js";
24
24
  /** Production data plane. Overridable for tests and for a self-hosted server. */
25
25
  export declare const DEFAULT_INGEST_URL = "https://api.vibecommit.ai/ingest/v1/session";
@@ -230,8 +230,10 @@ export type SendOutcome = {
230
230
  * ⚠ Read from the HEADER, never the body: `readErrorDetail` states that a
231
231
  * 2xx body is not read, not awaited and not parsed ON THE HOOK PATH, and
232
232
  * that property is why the hook's hot path cannot throw on a response. A
233
- * header costs a map lookup. (`connect` alone opts in to a 2xx body read,
234
- * for `conversation_id` — see `readConversationId`.)
233
+ * header costs a map lookup. (`connect` alone opts in to a 2xx body read of an
234
+ * INGEST reply, for `conversation_id` — see `readConversationId`. The only other 2xx
235
+ * body a hook reads is SessionStart's one bounded `GET /ingest/v1/grants`, which is
236
+ * not an ingest reply and does not go through `send` — see `hooks/session_grants.ts`.)
235
237
  */
236
238
  readonly captureId: string | null;
237
239
  /**
@@ -277,11 +279,48 @@ export type SendOutcome = {
277
279
  * credential-meta sidecar so state 5 can warn before the 365-day cap; it changes no disposition.
278
280
  */
279
281
  readonly credentialExpires?: string | null;
282
+ /**
283
+ * `X-Grant-Epoch` (slice 2, `CR-259`): the version of the user's account grants, on every credential-lane ingest 2xx and on a
284
+ * grants refusal. `null` when absent (a server that predates it) or not a non-negative integer.
285
+ *
286
+ * Read from the HEADER, like the others. It changes no disposition: `deliver` hands it to `noteGrantEpoch`, which marks
287
+ * `grants-account.json` stale when it is not the epoch this machine last recorded, and SessionStart's one bounded GET
288
+ * (`hooks/session_grants.ts`) is what answers that.
289
+ */
290
+ readonly grantEpoch?: number | null;
280
291
  }
281
292
  /** No response at all — DNS, refused, TLS, timeout. Not an HTTP status. */
282
293
  | {
283
294
  readonly kind: "unreachable";
284
295
  };
296
+ /**
297
+ * An error body is a handful of bytes by contract. Anything larger is not one
298
+ * this client parses — a cap so a misconfigured or hostile endpoint cannot make
299
+ * a hook buffer an arbitrary response into memory.
300
+ */
301
+ export declare const MAX_ERROR_BODY_BYTES: number;
302
+ /**
303
+ * ⛔ THE ONE CAPPED, TIMED BODY READER — `readErrorDetail` (non-2xx), `readConversationId` (`connect`'s opt-in
304
+ * 2xx) and `grants_sync.ts`'s two grants reads all read through it, so no bound can drift from another.
305
+ *
306
+ * Returns the parsed JSON (which may legitimately be `null`, an array or a scalar — the caller shapes it), or
307
+ * `undefined` for EVERY failure: no body, a declared length over the cap, a streamed body that crosses the cap,
308
+ * an abort, a stalled or reset stream, invalid JSON. **NEVER THROWS, on any input.**
309
+ *
310
+ * - BYTES: the declared `content-length` is checked first, and the stream is then counted chunk by chunk and
311
+ * CANCELLED the moment it crosses `maxBytes` (`MAX_ERROR_BODY_BYTES`, 64 KiB, unless a CLI verb asks for more) — so a chunked body with no length cannot be
312
+ * buffered whole before a post-hoc check (the old `await res.text()` did exactly that, contradicting
313
+ * `readErrorDetail`'s own comment that a hostile endpoint cannot make a hook buffer an arbitrary response).
314
+ * - TIME: every read is RACED against the request's abort signal rather than trusting the abort to reach the
315
+ * stream. Aborting is supposed to reject a pending `reader.read()` (it does, in a direct probe), but the
316
+ * bound is then a property of this function and not of the HTTP client's internals.
317
+ */
318
+ export declare function readCappedJson(res: Response, signal: AbortSignal, maxBytes?: number): Promise<unknown>;
319
+ /**
320
+ * `X-Grant-Epoch`: a non-negative integer, or null. Digits only (and a sane length), so a header that is not one reads as
321
+ * "the server did not say" and never as `NaN`, a negative, or a float that could equal nothing.
322
+ */
323
+ export declare function parseGrantEpoch(raw: string | null): number | null;
285
324
  /**
286
325
  * `X-Credential-Expires`: an ISO 8601 instant, or null. Only a string that parses as a date is believed —
287
326
  * the value is printed (as a date) to a person and compared against the clock, so a header that is not one
@@ -360,8 +399,29 @@ export type Delivery =
360
399
  readonly inferredSetAsidePairs: number;
361
400
  /** `X-Credential-Expires` from the 2xx that delivered this, or `null`/absent. See `SendOutcome`. */
362
401
  readonly credentialExpires?: string | null;
363
- /** `conversation_id` from that 2xx, ONLY when the caller opted in and `disposition === "ok"`. See `SendOutcome`. */
402
+ /**
403
+ * `conversation_id` from a 2xx, ONLY when the caller opted in. See `SendOutcome`.
404
+ *
405
+ * PR 4a (DX D8): a delivery of several deltas carries the id from whichever delta was acknowledged with it, even when
406
+ * a LATER delta came back `later`, so `connect`'s session link does not fall back to `/app/commits` on a partial run.
407
+ */
364
408
  readonly conversationId?: string;
409
+ /**
410
+ * PR 4a — records skipped because one record ALONE exceeded a limit (`record too large`): over `limits.rawBytes`
411
+ * raw, or over `limits.frameBytes` compressed, or refused with a 413 that no split can shrink. Each was written off
412
+ * with `markSkipped`, so it is in the gap counters `status` reports as "skipped … will not be sent later".
413
+ */
414
+ readonly recordsTooLarge?: number;
415
+ /**
416
+ * PR 5 — set when the last attempt got NO response at all (a refused connection, a timeout), so a caller can tell a server
417
+ * that could not be reached apart from one that answered and asked to wait. Absent whenever a response arrived. It
418
+ * changes no decision here: both are `later`.
419
+ */
420
+ readonly unreachable?: true;
421
+ /** PR 4a — deltas this call acknowledged or skipped past, when more than one. */
422
+ readonly deltas?: number;
423
+ /** PR 4a — `true` when the call stopped on the hook's budget with bytes still unsent. The offset is where it left off. */
424
+ readonly more?: boolean;
365
425
  };
366
426
  export interface DeliveryContext {
367
427
  readonly home: string;
@@ -444,23 +504,36 @@ export interface DeliveryContext {
444
504
  * reads, awaits or parses a 2xx body.
445
505
  */
446
506
  readonly readConversationId?: boolean;
507
+ /**
508
+ * PR 4a — WHEN THE HOOK'S SEND BUDGET ENDS, epoch ms. Set by the hook path only. `deliver()` starts a further delta (or a
509
+ * 413 split's retry) only while at least `MIN_NEXT_DELTA_BUDGET_MS` of it remains, and leaves the rest of the span for the
510
+ * next event or `vibecommit finalize`. Unset (`finalize`, `connect`) means no deadline.
511
+ */
512
+ readonly deadlineAtMs?: number;
513
+ /** PR 4a — the clock `deadlineAtMs` is measured on. A test seam; defaults to `Date.now`. */
514
+ readonly clock?: () => number;
515
+ /** PR 4a — the delta size limits. A test seam; defaults to the server-derived constants in `policy.ts`. */
516
+ readonly limits?: {
517
+ readonly rawBytes: number;
518
+ readonly frameBytes: number;
519
+ };
447
520
  }
448
521
  /**
449
- * Send the undelivered span of one transcript file and apply the failure policy.
522
+ * Send the undelivered span of one transcript file, in deltas — PR 4a.
450
523
  *
451
- * **At most one NETWORK attempt per hook, still — exactly D56 §D8's rule.** A
452
- * `finalize` lean retry (below) is the one exception D56 §D8 itself does not
453
- * cover: it governs HOOKS, and `finalize` is a synchronous, user-invoked verb
454
- * that already makes 1 + up to `FINALIZE_DRAIN_MAX_ITERATIONS` requests by
455
- * design (VL's explicit ruling, `TODOS[182]`). On the hook path, `later` still
456
- * does not retry here; it leaves the offset where it is so the hook that fires
457
- * on the NEXT turn picks the same bytes up.
524
+ * Without a `cutter` this is the single request it always was: everything from the offset to EOF, at most one attempt.
525
+ * With one (every production caller), the span goes out as record-aligned deltas, each acknowledged before the offset
526
+ * moves past it:
458
527
  *
459
- * Never throws: the caller is a hook, and an exception on this path is the
460
- * contract breaking. Every failure resolves to a `Delivery`.
528
+ * - **A hook sends deltas only while its budget lasts** (`ctx.deadlineAtMs`) and leaves the rest for its next event or
529
+ * `vibecommit finalize`; `Delivery.more` says it stopped early. `finalize` and `connect` set no deadline and run on.
530
+ * - **It stops at the first delta that is not `ok`** and returns that delta's outcome: `later` and `fatal` hold exactly
531
+ * the bytes that failed, so a resume starts at the next unacknowledged delta, with no resend and no gap. A
532
+ * `capture_not_approved` 403 on any delta is such a stop, so its pending beat is printed once.
533
+ * - **A skipped oversize record does not stop it.** The records after it still go out.
534
+ * - **`connect`'s conversation id survives a partial run** (DX D8): it is read from the first 2xx that carries it, no later
535
+ * delta reads a body, and it is returned even when a later delta came back `later`.
461
536
  *
462
- * `readBody` is supplied by the caller rather than read here, because the caller
463
- * is the one that has confined `transcript_path` to the Claude Code root
464
- * (`/cso` finding 1). This module never opens a file.
537
+ * ⛔ A 2xx never changes a delta's outcome, and a hook reads no body (eng-2 D2): the only body read is `connect`'s opt-in.
465
538
  */
466
- export declare function deliver(ctx: DeliveryContext, eof: number, readBody: (from: number, to: number) => Uint8Array | null): Promise<Delivery>;
539
+ export declare function deliver(ctx: DeliveryContext, eof: number, readBody: (from: number, to: number) => Uint8Array | null, cutter?: RecordCutter): Promise<Delivery>;