@vibe-commit/capture 0.1.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 (141) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +66 -0
  3. package/dist/agents/claude_code.d.ts +11 -0
  4. package/dist/agents/claude_code.js +162 -0
  5. package/dist/agents/claude_code.js.map +1 -0
  6. package/dist/agents/codex_cli.d.ts +15 -0
  7. package/dist/agents/codex_cli.js +67 -0
  8. package/dist/agents/codex_cli.js.map +1 -0
  9. package/dist/agents/cursor.d.ts +21 -0
  10. package/dist/agents/cursor.js +89 -0
  11. package/dist/agents/cursor.js.map +1 -0
  12. package/dist/agents/registry.d.ts +184 -0
  13. package/dist/agents/registry.js +212 -0
  14. package/dist/agents/registry.js.map +1 -0
  15. package/dist/agents/types.d.ts +279 -0
  16. package/dist/agents/types.js +67 -0
  17. package/dist/agents/types.js.map +1 -0
  18. package/dist/commands/connect.d.ts +36 -0
  19. package/dist/commands/connect.js +499 -0
  20. package/dist/commands/connect.js.map +1 -0
  21. package/dist/commands/context.d.ts +45 -0
  22. package/dist/commands/context.js +14 -0
  23. package/dist/commands/context.js.map +1 -0
  24. package/dist/commands/report.d.ts +105 -0
  25. package/dist/commands/report.js +430 -0
  26. package/dist/commands/report.js.map +1 -0
  27. package/dist/commands/status.d.ts +29 -0
  28. package/dist/commands/status.js +236 -0
  29. package/dist/commands/status.js.map +1 -0
  30. package/dist/commands/why.d.ts +349 -0
  31. package/dist/commands/why.js +937 -0
  32. package/dist/commands/why.js.map +1 -0
  33. package/dist/consent.d.ts +59 -0
  34. package/dist/consent.js +111 -0
  35. package/dist/consent.js.map +1 -0
  36. package/dist/copy/claims.d.ts +79 -0
  37. package/dist/copy/claims.js +343 -0
  38. package/dist/copy/claims.js.map +1 -0
  39. package/dist/copy/grades.d.ts +117 -0
  40. package/dist/copy/grades.js +96 -0
  41. package/dist/copy/grades.js.map +1 -0
  42. package/dist/copy/index.d.ts +12 -0
  43. package/dist/copy/index.js +13 -0
  44. package/dist/copy/index.js.map +1 -0
  45. package/dist/copy/strings.d.ts +1328 -0
  46. package/dist/copy/strings.js +1243 -0
  47. package/dist/copy/strings.js.map +1 -0
  48. package/dist/copy/time.d.ts +27 -0
  49. package/dist/copy/time.js +43 -0
  50. package/dist/copy/time.js.map +1 -0
  51. package/dist/credential.d.ts +211 -0
  52. package/dist/credential.js +298 -0
  53. package/dist/credential.js.map +1 -0
  54. package/dist/exit.d.ts +59 -0
  55. package/dist/exit.js +60 -0
  56. package/dist/exit.js.map +1 -0
  57. package/dist/git.d.ts +299 -0
  58. package/dist/git.js +653 -0
  59. package/dist/git.js.map +1 -0
  60. package/dist/hooks/entry.d.ts +277 -0
  61. package/dist/hooks/entry.js +1092 -0
  62. package/dist/hooks/entry.js.map +1 -0
  63. package/dist/hooks/post_commit.d.ts +59 -0
  64. package/dist/hooks/post_commit.js +160 -0
  65. package/dist/hooks/post_commit.js.map +1 -0
  66. package/dist/hooks/post_rewrite.d.ts +59 -0
  67. package/dist/hooks/post_rewrite.js +161 -0
  68. package/dist/hooks/post_rewrite.js.map +1 -0
  69. package/dist/hooks/session_end.d.ts +101 -0
  70. package/dist/hooks/session_end.js +120 -0
  71. package/dist/hooks/session_end.js.map +1 -0
  72. package/dist/index.d.ts +34 -0
  73. package/dist/index.js +360 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/install.d.ts +153 -0
  76. package/dist/install.js +284 -0
  77. package/dist/install.js.map +1 -0
  78. package/dist/json.d.ts +100 -0
  79. package/dist/json.js +94 -0
  80. package/dist/json.js.map +1 -0
  81. package/dist/oauth/discovery.d.ts +96 -0
  82. package/dist/oauth/discovery.js +163 -0
  83. package/dist/oauth/discovery.js.map +1 -0
  84. package/dist/oauth/lock.d.ts +100 -0
  85. package/dist/oauth/lock.js +287 -0
  86. package/dist/oauth/lock.js.map +1 -0
  87. package/dist/oauth/loopback.d.ts +85 -0
  88. package/dist/oauth/loopback.js +124 -0
  89. package/dist/oauth/loopback.js.map +1 -0
  90. package/dist/oauth/pkce.d.ts +58 -0
  91. package/dist/oauth/pkce.js +77 -0
  92. package/dist/oauth/pkce.js.map +1 -0
  93. package/dist/oauth/read.d.ts +120 -0
  94. package/dist/oauth/read.js +144 -0
  95. package/dist/oauth/read.js.map +1 -0
  96. package/dist/oauth/session.d.ts +80 -0
  97. package/dist/oauth/session.js +112 -0
  98. package/dist/oauth/session.js.map +1 -0
  99. package/dist/oauth/signin.d.ts +178 -0
  100. package/dist/oauth/signin.js +225 -0
  101. package/dist/oauth/signin.js.map +1 -0
  102. package/dist/oauth/token.d.ts +139 -0
  103. package/dist/oauth/token.js +183 -0
  104. package/dist/oauth/token.js.map +1 -0
  105. package/dist/paths.d.ts +366 -0
  106. package/dist/paths.js +460 -0
  107. package/dist/paths.js.map +1 -0
  108. package/dist/policy.d.ts +195 -0
  109. package/dist/policy.js +244 -0
  110. package/dist/policy.js.map +1 -0
  111. package/dist/post.d.ts +302 -0
  112. package/dist/post.js +384 -0
  113. package/dist/post.js.map +1 -0
  114. package/dist/project.d.ts +99 -0
  115. package/dist/project.js +192 -0
  116. package/dist/project.js.map +1 -0
  117. package/dist/redact.d.ts +175 -0
  118. package/dist/redact.js +700 -0
  119. package/dist/redact.js.map +1 -0
  120. package/dist/runtime.d.ts +30 -0
  121. package/dist/runtime.js +37 -0
  122. package/dist/runtime.js.map +1 -0
  123. package/dist/spawn_budget.d.ts +101 -0
  124. package/dist/spawn_budget.js +124 -0
  125. package/dist/spawn_budget.js.map +1 -0
  126. package/dist/spool.d.ts +390 -0
  127. package/dist/spool.js +556 -0
  128. package/dist/spool.js.map +1 -0
  129. package/dist/state.d.ts +109 -0
  130. package/dist/state.js +217 -0
  131. package/dist/state.js.map +1 -0
  132. package/dist/system_message.d.ts +101 -0
  133. package/dist/system_message.js +141 -0
  134. package/dist/system_message.js.map +1 -0
  135. package/dist/term.d.ts +112 -0
  136. package/dist/term.js +134 -0
  137. package/dist/term.js.map +1 -0
  138. package/dist/version.d.ts +16 -0
  139. package/dist/version.js +17 -0
  140. package/dist/version.js.map +1 -0
  141. package/package.json +50 -0
@@ -0,0 +1,120 @@
1
+ /**
2
+ * `SessionEnd` settles before it reads — `CR-020d`, D57 §DX7.
3
+ *
4
+ * The finding, verbatim: *"`SessionEnd` settles and re-reads inside its timeout.
5
+ * `transcript_path` is documented as written asynchronously and may lag;
6
+ * `SessionEnd` has no next event, so D56's advance-regardless loses the final
7
+ * turn **permanently**."*
8
+ *
9
+ * ## Why only this event
10
+ *
11
+ * The client's whole design tolerates a lagging write: read what is there, leave
12
+ * the offset where it lands, and let the NEXT invocation pick up whatever the
13
+ * write had not flushed yet. `Stop` and `PreCompact` both have a next
14
+ * invocation. `SessionEnd` does not — it is the last hook of the session, so
15
+ * bytes missed here are missed forever, and they are the bytes of the final
16
+ * turn, which is the one a user is most likely to go looking for.
17
+ *
18
+ * So the fix is narrow on purpose: one event pays the cost, and `Stop` behaves
19
+ * exactly as it did before this task. `test/contract.test.ts` asserts that
20
+ * negative half directly, because a change that quietly made every event settle
21
+ * would pass the positive test just as well.
22
+ *
23
+ * ## One wait, not a poll loop
24
+ *
25
+ * The task is "settle-and-reread", singular. D56 §D8 is a founder override that
26
+ * a hook must never block or slow a developer's turn, and "wait until the file
27
+ * stops growing" has no natural upper bound — under load it is unbounded exactly
28
+ * when blocking is least affordable. A single named wait is the simplest thing
29
+ * that closes the finding, and its cost is knowable by reading one constant.
30
+ *
31
+ * ## This module holds no I/O and no clock
32
+ *
33
+ * `settledSize` takes both, for the same reason `policy.ts` is pure: the whole
34
+ * settle rule is then testable without a real 250 ms of wall clock and without a
35
+ * filesystem, and the one place that does touch either is the caller.
36
+ */
37
+ /**
38
+ * The event name Claude Code sends on stdin as `hook_event_name` for the last
39
+ * hook of a session. DESIGN.md §13.7 governs it alongside `Stop` and
40
+ * `PreCompact`; this task changes WHEN bytes are read, never the exit contract.
41
+ */
42
+ export const SESSION_END_EVENT = "SessionEnd";
43
+ /**
44
+ * How long to let the transcript settle. **250 ms, and the number is reasoned.**
45
+ *
46
+ * The lag being covered is a local filesystem write-flush artifact — Claude
47
+ * Code's own process appending JSONL lines to a file this process is about to
48
+ * stat — not a network round trip. That puts the expected lag in the
49
+ * tens-of-milliseconds range, so 250 ms is roughly an order of magnitude of
50
+ * margin over the effect it is covering, while staying a twentieth of the
51
+ * default 5 s budget.
52
+ *
53
+ * It is deliberately NOT larger. Every millisecond here is taken from the send
54
+ * that follows (see `settleDelayMs`), and a settle generous enough to cover a
55
+ * pathologically slow write would starve the upload it exists to make complete.
56
+ * If evidence ever shows real lag above this, change the constant and say why —
57
+ * it is one number in one place precisely so that stays cheap.
58
+ */
59
+ export const SESSION_END_SETTLE_DELAY_MS = 250;
60
+ /**
61
+ * The most of the hook's budget the settle may ever claim.
62
+ *
63
+ * The settle is carved OUT of the existing budget, never added on top of it, so
64
+ * it competes with the send. This cap is what keeps the constant above safe at
65
+ * any budget: on the 5 s default it never binds (0.3 × 5000 = 1500 ≫ 250), and
66
+ * on a budget small enough that a flat 250 ms would swallow the invocation it
67
+ * scales the settle down instead of eating the send.
68
+ */
69
+ export const SETTLE_BUDGET_FRACTION = 0.3;
70
+ /**
71
+ * How long to actually settle, given this invocation's whole budget.
72
+ *
73
+ * The override exists for the same two reasons `resolveCaps` has one
74
+ * (`policy.ts`): an operator on a filesystem slower than this constant assumes
75
+ * can raise it without a release, and the end-to-end test has to widen the
76
+ * window to land an append inside it deterministically rather than racing a
77
+ * child's boot — which varies by an order of magnitude under load (`CR-126`).
78
+ *
79
+ * Unset or unparseable takes the default rather than disabling the settle: a
80
+ * window an empty string can switch off is not a window. The budget cap still
81
+ * applies to the override, so it can widen the settle but never let it swallow
82
+ * the send.
83
+ */
84
+ export function settleDelayMs(env, budgetMs) {
85
+ const raw = env.VIBECOMMIT_SESSION_END_SETTLE_MS;
86
+ const parsed = raw === undefined ? NaN : Number(raw);
87
+ const configured = Number.isFinite(parsed) && parsed > 0 ? parsed : SESSION_END_SETTLE_DELAY_MS;
88
+ return Math.min(configured, Math.floor(budgetMs * SETTLE_BUDGET_FRACTION));
89
+ }
90
+ /**
91
+ * The transcript's size after letting a lagging write land.
92
+ *
93
+ * Read, wait, read again, and take the LARGER. Growth is the case this exists
94
+ * for: the first read raced a write in progress, and the second sees the final
95
+ * turn the first one missed.
96
+ *
97
+ * **A SHORTER second read keeps the first.** That is truncation or rotation — a
98
+ * different and much rarer failure mode, which this task deliberately does not
99
+ * try to solve; `nextSpan` already resyncs from 0 when the offset sits past EOF,
100
+ * and `readSpan` already sends only the bytes actually present. Named as a known
101
+ * gap rather than handled speculatively.
102
+ *
103
+ * A `null` second read (the file went away mid-settle) also keeps the first, for
104
+ * the same reason: what we saw is better evidence than what we can no longer see.
105
+ */
106
+ export async function settledSize(sizeOf, wait, delayMs) {
107
+ const first = sizeOf();
108
+ // Nothing to settle toward — the caller treats null as "do not send", and a
109
+ // wait would spend budget to learn the same thing again.
110
+ if (first === null)
111
+ return null;
112
+ if (delayMs <= 0)
113
+ return first;
114
+ await wait(delayMs);
115
+ const second = sizeOf();
116
+ if (second === null)
117
+ return first;
118
+ return second > first ? second : first;
119
+ }
120
+ //# sourceMappingURL=session_end.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session_end.js","sourceRoot":"","sources":["../../src/hooks/session_end.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,YAAY,CAAC;AAE9C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAE/C;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAE1C;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,aAAa,CAAC,GAAsB,EAAE,QAAgB;IACpE,MAAM,GAAG,GAAG,GAAG,CAAC,gCAAgC,CAAC;IACjD,MAAM,MAAM,GAAG,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrD,MAAM,UAAU,GACd,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,2BAA2B,CAAC;IAC/E,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,sBAAsB,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAA2B,EAC3B,IAAmC,EACnC,OAAe;IAEf,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC;IACvB,4EAA4E;IAC5E,yDAAyD;IACzD,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAChC,IAAI,OAAO,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAE/B,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC;IAEpB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAClC,OAAO,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;AACzC,CAAC"}
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+ import { type InvocationMode } from "./exit.js";
3
+ declare const VERBS: readonly ["connect", "status", "off", "why", "report"];
4
+ export type Verb = (typeof VERBS)[number];
5
+ export declare function isVerb(value: string): value is Verb;
6
+ /**
7
+ * Hook invocations are distinguished by ARGV FIRST, then by env.
8
+ *
9
+ * ⚠ `CLAUDE_HOOK_EVENT` is **not** a variable Claude Code sets. The documented
10
+ * contract puts `hook_event_name` on **stdin JSON**, and the environment carries
11
+ * `CLAUDE_PROJECT_DIR` / `CLAUDE_PLUGIN_ROOT` — neither of which identifies a
12
+ * hook event. Keying the mode off that variable alone would make every hook
13
+ * invocation run in INTERACTIVE mode, which is the shape of a contract test that
14
+ * passes while testing nothing.
15
+ *
16
+ * So the primary signal is the one we control: `CR-028`'s `hooks.json` invokes
17
+ * `vibecommit hook`. The env var is kept as a secondary because the scaffold
18
+ * established it and a wrapper may already set it.
19
+ */
20
+ export declare function invocationMode(env: NodeJS.ProcessEnv, argv: readonly string[]): InvocationMode;
21
+ /**
22
+ * `--help`, wrapped hard at 80 columns per DESIGN.md §13.4.
23
+ *
24
+ * Never reflows to `process.stdout.columns`: identical commands must emit
25
+ * identical bytes, or issue-paste, screenshots and every golden-file test of the
26
+ * copy break. `test/help-golden.test.ts` is that golden file.
27
+ *
28
+ * No SGR here at all. Colour would have to be resolved before help could be
29
+ * rendered, and help is the one surface where structure alone is enough —
30
+ * indentation and the label gutter carry it, which is §13.1's point about
31
+ * `NO_COLOR` being a lossless degradation rather than a downgrade.
32
+ */
33
+ export declare function renderHelp(): string;
34
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,360 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * `vibecommit` — CLI entry point.
4
+ *
5
+ * Verb bodies that are NOT here, each an owned task in
6
+ * `coordination/CAPTURE_REFACTOR_TASKS.md`:
7
+ *
8
+ * why CR-086 report CR-108 connect's live-capture ending CR-025
9
+ * status/off output spec CR-021 failure policy CR-018
10
+ * repo binding key + X-Repo-Slug CR-017 / CR-019
11
+ *
12
+ * What IS established here, and must not be undone by those tasks:
13
+ * - no user-facing string literal in a command body (CR-090 → `src/copy/`)
14
+ * - the exit-code contract is split hook vs interactive (CR-022 → `src/exit.ts`)
15
+ * - one commit-header renderer taking the grade (CR-090 → `src/copy/grades.ts`)
16
+ * - every escape sequence comes from `src/term.ts` (DESIGN.md §13.2)
17
+ * - the hook contract is enforced by the entry, not by each verb
18
+ */
19
+ import { writeSync } from "node:fs";
20
+ import { homedir } from "node:os";
21
+ import { createInterface } from "node:readline/promises";
22
+ import { resolveAgentId } from "./agents/registry.js";
23
+ import { connect } from "./commands/connect.js";
24
+ import { off, status } from "./commands/status.js";
25
+ import { report } from "./commands/report.js";
26
+ import { why } from "./commands/why.js";
27
+ import { HELP, INTERNAL, USAGE } from "./copy/index.js";
28
+ import { EXIT } from "./exit.js";
29
+ import { runHook } from "./hooks/entry.js";
30
+ import { runPostCommit } from "./hooks/post_commit.js";
31
+ import { runPostRewrite } from "./hooks/post_rewrite.js";
32
+ import { LABEL_GUTTER, renderErrorBlock, resolveColour, wrap } from "./term.js";
33
+ import { CLIENT_VERSION } from "./version.js";
34
+ const VERBS = ["connect", "status", "off", "why", "report"];
35
+ export function isVerb(value) {
36
+ return VERBS.includes(value);
37
+ }
38
+ /**
39
+ * Hook invocations are distinguished by ARGV FIRST, then by env.
40
+ *
41
+ * ⚠ `CLAUDE_HOOK_EVENT` is **not** a variable Claude Code sets. The documented
42
+ * contract puts `hook_event_name` on **stdin JSON**, and the environment carries
43
+ * `CLAUDE_PROJECT_DIR` / `CLAUDE_PLUGIN_ROOT` — neither of which identifies a
44
+ * hook event. Keying the mode off that variable alone would make every hook
45
+ * invocation run in INTERACTIVE mode, which is the shape of a contract test that
46
+ * passes while testing nothing.
47
+ *
48
+ * So the primary signal is the one we control: `CR-028`'s `hooks.json` invokes
49
+ * `vibecommit hook`. The env var is kept as a secondary because the scaffold
50
+ * established it and a wrapper may already set it.
51
+ */
52
+ export function invocationMode(env, argv) {
53
+ if (argv[0] === "hook")
54
+ return "hook";
55
+ return env.CLAUDE_HOOK_EVENT ? "hook" : "interactive";
56
+ }
57
+ /**
58
+ * `--help`, wrapped hard at 80 columns per DESIGN.md §13.4.
59
+ *
60
+ * Never reflows to `process.stdout.columns`: identical commands must emit
61
+ * identical bytes, or issue-paste, screenshots and every golden-file test of the
62
+ * copy break. `test/help-golden.test.ts` is that golden file.
63
+ *
64
+ * No SGR here at all. Colour would have to be resolved before help could be
65
+ * rendered, and help is the one surface where structure alone is enough —
66
+ * indentation and the label gutter carry it, which is §13.1's point about
67
+ * `NO_COLOR` being a lossless degradation rather than a downgrade.
68
+ */
69
+ export function renderHelp() {
70
+ const lines = [
71
+ ...wrap(HELP.tagline, 2),
72
+ "",
73
+ ...wrap(`${USAGE.usageLabel} ${HELP.usage}`, 2),
74
+ "",
75
+ ...wrap(USAGE.commandsLabel, 2),
76
+ ];
77
+ for (const verb of VERBS) {
78
+ // The description is wrapped on its own and the verb column is written over
79
+ // the first line's indent. Wrapping `verb + padding + description` as one
80
+ // string would not work: `wrap` normalises whitespace, so the fixed gutter
81
+ // would collapse to a single space.
82
+ const head = ` ${verb.padEnd(LABEL_GUTTER)}`;
83
+ const body = wrap(HELP.commands[verb], head.length);
84
+ lines.push(head + body[0].slice(head.length), ...body.slice(1));
85
+ }
86
+ lines.push("", ...wrap(`${USAGE.docsLabel} ${HELP.docsUrl}`, 2));
87
+ return lines.join("\n");
88
+ }
89
+ function interactiveContext(argv) {
90
+ return {
91
+ env: process.env,
92
+ home: homedir(),
93
+ cwd: process.cwd(),
94
+ nodeVersion: process.versions.node,
95
+ // `CR-183`. Resolved from argv HERE, the same pure read the hook branch at
96
+ // the bottom of this file makes — `connect` needs it to know whether the
97
+ // agent it was told about has a way to find the running session at all.
98
+ agentId: resolveAgentId(argv),
99
+ colour: resolveColour({
100
+ env: process.env,
101
+ isTty: process.stdout.isTTY === true,
102
+ noColorFlag: argv.includes("--no-color"),
103
+ json: argv.includes("--json"),
104
+ }),
105
+ stdinIsTty: process.stdin.isTTY === true,
106
+ stdout: process.stdout,
107
+ stderr: process.stderr,
108
+ /**
109
+ * The readline interface is created HERE, on the first question, and not
110
+ * once per invocation — CR-117.
111
+ *
112
+ * `createInterface` RESUMES stdin, and a resumed stdin keeps the event loop
113
+ * alive until it ends. Built eagerly, a verb that returns without ever
114
+ * prompting sat there until the pipe closed: `connect` refusing a non-TTY,
115
+ * and `status` / `off`, which never ask anything. On a terminal that looked
116
+ * fine, because stdin ends at EOF; under `cmd | vibecommit connect` in CI it
117
+ * is the hang the source finding names first, burning the job's whole
118
+ * timeout with the refusal already on screen and no way to explain it.
119
+ *
120
+ * It also makes style guide §10.2 rule 2 literally true rather than nearly
121
+ * true: on the refusal path stdin is not read, resumed, or opened at all.
122
+ */
123
+ ask: async (question) => {
124
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
125
+ try {
126
+ return await rl.question(question);
127
+ }
128
+ finally {
129
+ rl.close();
130
+ }
131
+ },
132
+ now: () => new Date(),
133
+ selfPath: process.argv[1] ?? "",
134
+ };
135
+ }
136
+ async function main(argv) {
137
+ const [verb] = argv;
138
+ if (verb === undefined || verb === "--help" || verb === "-h") {
139
+ process.stdout.write(`${renderHelp()}\n`);
140
+ return EXIT.ok;
141
+ }
142
+ if (verb === "--version" || verb === "-v") {
143
+ process.stdout.write(`${CLIENT_VERSION}\n`);
144
+ return EXIT.ok;
145
+ }
146
+ if (!isVerb(verb)) {
147
+ process.stderr.write(`${USAGE.unknownCommand(verb)}\n\n${renderHelp()}\n`);
148
+ return EXIT.usage;
149
+ }
150
+ const ctx = interactiveContext(argv);
151
+ switch (verb) {
152
+ case "connect":
153
+ // `--sign-in` (CR-084d) is a FLAG, not a verb: `VERBS` is what `renderHelp`
154
+ // iterates, so a sixth verb would move `test/help.golden.txt`, and the
155
+ // brief for this task is explicit that the golden file must not move.
156
+ return await connect(ctx, { signIn: argv.includes("--sign-in") });
157
+ case "status":
158
+ // `argv.slice(1)` for the same reason `why` and `report` take it: `status`
159
+ // reads its own `--json` flag rather than this package acquiring an
160
+ // argument parser it has deliberately never had (DESIGN.md §13.3).
161
+ return status(ctx, argv.slice(1));
162
+ case "off":
163
+ return off(ctx);
164
+ case "why":
165
+ // CR-086. `argv.slice(1)` is everything after the verb — there is no
166
+ // argument parser in this package and `why` does not add one; it reads
167
+ // `<file>:<line>` and refuses `--json`, which is the smallest shape that
168
+ // satisfies the verbatim-approved `--help` sentence.
169
+ return await why(ctx, argv.slice(1));
170
+ case "report":
171
+ // CR-108, W10. Same shape as `why`: `argv.slice(1)` is everything after
172
+ // the verb, and the verb reads its own two flags rather than adding an
173
+ // argument parser this package deliberately does not have.
174
+ return await report(ctx, argv.slice(1));
175
+ }
176
+ }
177
+ function readStdin() {
178
+ return new Promise((resolve) => {
179
+ let buf = "";
180
+ process.stdin.setEncoding("utf8");
181
+ process.stdin.on("data", (chunk) => {
182
+ buf += chunk;
183
+ });
184
+ process.stdin.on("end", () => resolve(buf));
185
+ process.stdin.on("error", () => resolve(""));
186
+ });
187
+ }
188
+ /**
189
+ * The INTERACTIVE half of the split exit contract — CR-022, D61 round 3 §D8.
190
+ *
191
+ * The hook half is enforced in `hooks/entry.ts`: swallow everything, exit 0, stay
192
+ * silent, because a non-zero hook feeds stderr back into the user's agent and
193
+ * derails the task they were actually doing. **An interactive verb must not
194
+ * inherit that blanket.** As originally written the exit-0/stdout-empty rule read
195
+ * as governing the whole binary, which would make `why` on a read-lane 5xx exit 0
196
+ * and print nothing — a read verb failing silently, which is the defect this
197
+ * split exists to prevent.
198
+ *
199
+ * So: same fault, same binary, two modes, two behaviours. Interactive gets exit 1
200
+ * and §13.6's shape.
201
+ *
202
+ * Two things this deliberately does NOT do:
203
+ * - **No signal handling.** `Ctrl-C` cancelling a `connect` prompt is normal
204
+ * CLI behaviour, and suppressing `SIGINT` globally would be a UX regression
205
+ * dressed up as a fix. The hook's signal override stays scoped to hook mode.
206
+ * - **No stack trace** unless `VIBECOMMIT_DEBUG` is set (§13.6, first
207
+ * prohibition). The detail then goes out RAW, after the block, rather than
208
+ * through `wrap()`, which would reflow a stack into nonsense.
209
+ */
210
+ function reportUnexpected(error, argv) {
211
+ const colour = resolveColour({
212
+ env: process.env,
213
+ isTty: process.stderr.isTTY === true,
214
+ noColorFlag: argv.includes("--no-color"),
215
+ json: argv.includes("--json"),
216
+ });
217
+ const lines = renderErrorBlock({
218
+ kind: "bad",
219
+ what: INTERNAL.unexpectedWhat,
220
+ why: [INTERNAL.unexpectedWhy],
221
+ fixLabel: INTERNAL.unexpectedFix,
222
+ fixes: [INTERNAL.unexpectedDebugCommand],
223
+ }, colour);
224
+ if (process.env.VIBECOMMIT_DEBUG !== undefined)
225
+ lines.push("", detailOf(error));
226
+ // `writeSync(2, …)` rather than `process.stderr.write`: stderr to a pipe is
227
+ // asynchronous and `process.exit` does not flush it, so the caller below would
228
+ // race its own diagnostic away. Same reason `finish()` uses it on fd 1.
229
+ try {
230
+ writeSync(2, `${lines.join("\n")}\n`);
231
+ }
232
+ catch {
233
+ // An unwritable stderr is not worth a second exception on this path.
234
+ }
235
+ }
236
+ /**
237
+ * The raw detail, for `VIBECOMMIT_DEBUG` only.
238
+ *
239
+ * Interpolating an error is safe by construction here: an `IngestCredential`
240
+ * renders `vcik_…redacted` through `toString`, `toJSON` and the inspect hook, so
241
+ * a stack that embedded one cannot print the plaintext.
242
+ */
243
+ function detailOf(error) {
244
+ if (error instanceof Error && typeof error.stack === "string")
245
+ return error.stack;
246
+ return String(error);
247
+ }
248
+ /**
249
+ * Catch what escapes `main()` entirely — a stray timer's throw, a rejection from
250
+ * a promise nobody awaited. Without these, Node prints its own stack trace to
251
+ * stderr, which §13.6 forbids outright.
252
+ *
253
+ * These force an exit rather than setting `process.exitCode`, because by
254
+ * definition something unexpected is still in flight and may be holding the event
255
+ * loop open. The `main()` rejection path below does not: nothing is in flight
256
+ * there, and letting the loop drain preserves whatever the verb already wrote.
257
+ */
258
+ function installInteractiveGuards(argv) {
259
+ const fail = (error) => {
260
+ reportUnexpected(error, argv);
261
+ process.exit(EXIT.failure);
262
+ };
263
+ process.on("uncaughtException", fail);
264
+ process.on("unhandledRejection", fail);
265
+ }
266
+ /**
267
+ * Swallow EPIPE.
268
+ *
269
+ * `vibecommit --help | head` closes stdout mid-write, and Node's default for an
270
+ * unhandled stream error is to print a stack trace and exit non-zero. §13.6
271
+ * forbids the stack trace outright, and a non-zero exit for an ordinary
272
+ * `| head` would teach a wrapper script that the command failed.
273
+ */
274
+ function installPipeGuards() {
275
+ for (const stream of [process.stdout, process.stderr]) {
276
+ stream.on("error", (err) => {
277
+ if (err.code === "EPIPE")
278
+ process.exit(EXIT.ok);
279
+ });
280
+ }
281
+ }
282
+ // Only run when executed as the binary, so tests can import the module freely.
283
+ if (process.argv[1] && import.meta.url === `file://${process.argv[1]}`) {
284
+ installPipeGuards();
285
+ const argv = process.argv.slice(2);
286
+ if (argv[0] === "post-commit") {
287
+ // ⛔ A HIDDEN VERB, dispatched here rather than through `main`, and NOT in
288
+ // `VERBS` — `renderHelp` iterates that list, so adding it would move
289
+ // `test/help.golden.txt` for a verb no human ever types. `hook` is dispatched
290
+ // the same way, for the same reason.
291
+ //
292
+ // It runs inside the user's `git commit`, so it exits 0 unconditionally and
293
+ // writes nothing to either stream (`hooks/post_commit.ts`).
294
+ //
295
+ // ⛔ `env` IS THE LADDER'S FIRST RUNG. Claude Code exports
296
+ // `CLAUDE_CODE_SESSION_ID` into the Bash tool's environment and git passes it
297
+ // through to us (`M1`), so the committing session identifies ITSELF instead of
298
+ // being guessed at by mtime. This is the one place the real environment is
299
+ // read on this path; everything below takes it as a parameter.
300
+ process.exit(runPostCommit({ home: homedir(), cwd: process.cwd(), env: process.env }));
301
+ }
302
+ if (argv[0] === "post-rewrite") {
303
+ // The other hidden verb, for the same reason — and it is `post-commit`'s
304
+ // other half: `--amend` and `rebase` fire `post-commit` for a sha they then
305
+ // DESTROY (`M5`), and this is the only hook git tells about the pairing.
306
+ //
307
+ // ⛔ THE PAIRS ARRIVE ON STDIN, and it is read HERE so `hooks/post_rewrite.ts`
308
+ // opens nothing — the same seam that keeps every other module in this package
309
+ // free of a real file descriptor. ⚠ `readStdin` REUSED rather than a second
310
+ // synchronous reader beside it: it already resolves an `error` to `""`, and
311
+ // two stdin readers in one file is how the two come to disagree about what an
312
+ // unreadable stream means. An empty read parses to zero pairs, which is an
313
+ // ordinary answer rather than a failure.
314
+ void readStdin().then((stdin) => process.exit(runPostRewrite({
315
+ home: homedir(),
316
+ cwd: process.cwd(),
317
+ env: process.env,
318
+ // git's own `argv[1]` — `amend` or `rebase`.
319
+ kind: argv[1] ?? "",
320
+ stdin,
321
+ })));
322
+ // ⛔ `else if` FROM HERE, AND THE BRANCH ABOVE IS WHY. Reading stdin is
323
+ // asynchronous, so unlike `post-commit` this block RETURNS rather than
324
+ // exiting — and a plain `if` below would then run `main(["post-rewrite"])`
325
+ // synchronously, print an unknown-verb error, and put it in the terminal of
326
+ // someone in the middle of a `git rebase`. The contract this hook is held to
327
+ // is silence.
328
+ }
329
+ else if (invocationMode(process.env, argv) === "hook") {
330
+ // `runHook` installs the contract guards before it does any work and always
331
+ // calls `process.exit(0)`. It never returns, so nothing follows it.
332
+ void runHook({
333
+ env: process.env,
334
+ home: homedir(),
335
+ nodeVersion: process.versions.node,
336
+ // ⛔ `CR-183` — THE ONE PLACE THE FLAG IS READ ON THIS PATH, and it is read
337
+ // HERE rather than inside the hook for a structural reason: `runHook` never
338
+ // receives argv at all, and `parseHookInput` must not select the adapter
339
+ // because stdin is the input the confinement boundary exists to constrain.
340
+ // This is the seam that already injects `home` and `nodeVersion`.
341
+ //
342
+ // ⚠ Note what the line ABOVE this block does and does not do: resolving an
343
+ // id is not entering hook mode. `invocationMode` keys on `argv[0]`, so the
344
+ // registered command MUST lead with the `hook` verb — put the flag first
345
+ // and this branch is never taken.
346
+ agentId: resolveAgentId(argv),
347
+ readStdin,
348
+ });
349
+ }
350
+ else {
351
+ installInteractiveGuards(argv);
352
+ void main(argv).then((code) => {
353
+ process.exitCode = code;
354
+ }, (error) => {
355
+ reportUnexpected(error, argv);
356
+ process.exitCode = EXIT.failure;
357
+ });
358
+ }
359
+ }
360
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}