@mmnto/cli 1.100.0 → 1.101.1

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 (51) hide show
  1. package/dist/commands/doctor-parity.d.ts.map +1 -1
  2. package/dist/commands/doctor-parity.js +11 -5
  3. package/dist/commands/doctor-parity.js.map +1 -1
  4. package/dist/commands/doctor.d.ts +19 -0
  5. package/dist/commands/doctor.d.ts.map +1 -1
  6. package/dist/commands/doctor.js +132 -0
  7. package/dist/commands/doctor.js.map +1 -1
  8. package/dist/commands/doctor.test.js +1 -0
  9. package/dist/commands/doctor.test.js.map +1 -1
  10. package/dist/commands/gate-install.d.ts.map +1 -1
  11. package/dist/commands/gate-install.js +12 -3
  12. package/dist/commands/gate-install.js.map +1 -1
  13. package/dist/commands/gate-install.test.js +13 -1
  14. package/dist/commands/gate-install.test.js.map +1 -1
  15. package/dist/commands/init-templates.d.ts +57 -5
  16. package/dist/commands/init-templates.d.ts.map +1 -1
  17. package/dist/commands/init-templates.js +222 -1
  18. package/dist/commands/init-templates.js.map +1 -1
  19. package/dist/commands/init.d.ts +38 -4
  20. package/dist/commands/init.d.ts.map +1 -1
  21. package/dist/commands/init.js +196 -13
  22. package/dist/commands/init.js.map +1 -1
  23. package/dist/commands/init.test.js +13 -0
  24. package/dist/commands/init.test.js.map +1 -1
  25. package/dist/commands/install-hooks-exit-contract.test.d.ts +2 -0
  26. package/dist/commands/install-hooks-exit-contract.test.d.ts.map +1 -0
  27. package/dist/commands/install-hooks-exit-contract.test.js +508 -0
  28. package/dist/commands/install-hooks-exit-contract.test.js.map +1 -0
  29. package/dist/commands/install-hooks.d.ts +53 -0
  30. package/dist/commands/install-hooks.d.ts.map +1 -1
  31. package/dist/commands/install-hooks.js +277 -42
  32. package/dist/commands/install-hooks.js.map +1 -1
  33. package/dist/commands/mail.d.ts.map +1 -1
  34. package/dist/commands/mail.js +56 -16
  35. package/dist/commands/mail.js.map +1 -1
  36. package/dist/commands/mail.test.js +73 -0
  37. package/dist/commands/mail.test.js.map +1 -1
  38. package/dist/commands/prepare-wrapper.test.d.ts +2 -0
  39. package/dist/commands/prepare-wrapper.test.d.ts.map +1 -0
  40. package/dist/commands/prepare-wrapper.test.js +284 -0
  41. package/dist/commands/prepare-wrapper.test.js.map +1 -0
  42. package/dist/parse-nits.d.ts +20 -3
  43. package/dist/parse-nits.d.ts.map +1 -1
  44. package/dist/parse-nits.js +111 -6
  45. package/dist/parse-nits.js.map +1 -1
  46. package/dist/parse-nits.test.js +141 -0
  47. package/dist/parse-nits.test.js.map +1 -1
  48. package/dist/parsers/bot-review-parser.d.ts.map +1 -1
  49. package/dist/parsers/bot-review-parser.js +12 -2
  50. package/dist/parsers/bot-review-parser.js.map +1 -1
  51. package/package.json +2 -2
@@ -0,0 +1,508 @@
1
+ /**
2
+ * Exit-code contract for `totem hook install` (`hooksCommand`) + the managed
3
+ * session-hook bounded drift-repair (mmnto-ai/totem#2410 PR-A, slices 2+3).
4
+ *
5
+ * This is the dedicated falsifying test for the contract #2406 stabilized and
6
+ * strategy#894 froze (Tenet 19). It locks:
7
+ * - exit 0 ⟺ {fresh install, already-current, bounded drift-repair (git hook AND
8
+ * session hook), declared skips (not-a-git-repo, hook-manager-detected)};
9
+ * - exit ≠0 ⟺ genuine failure (a hook write throws → propagates → handleError);
10
+ * - `--check` is exactly 0/1 (all-present-with-marker vs missing/markerless);
11
+ * - a bare install never mutates a non-bounded file (git hook OR session hook);
12
+ * `--force` is the only unbounded write; a legacy markerless-end session hook is
13
+ * never bare-repaired; a no-marker user file is never touched even under --force;
14
+ * - regenerated artifacts always carry marker + end marker (so they self-repair);
15
+ * - the two `overwritten` messages are distinct ("Drift-repaired…" vs
16
+ * "Force-overwritten…").
17
+ *
18
+ * `hooksCommand` reads `process.cwd()` and gates via `process.exit` on `--check`
19
+ * failure, so the exit-code cases drive it under `process.chdir` + a `process.exit`
20
+ * spy (the doctor.test.ts idiom); the session-hook matrix drives the pure
21
+ * `regenerateManagedSessionHooks(cwd, force)` seam directly.
22
+ */
23
+ import { execFileSync, execSync } from 'node:child_process';
24
+ import * as fs from 'node:fs';
25
+ import * as os from 'node:os';
26
+ import * as path from 'node:path';
27
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
28
+ import { cleanTmpDir } from '../test-utils.js';
29
+ import { CLAUDE_PREWRITESHIELD, CLAUDE_SESSION_START, GEMINI_SESSION_START, MANAGED_SESSION_HOOKS, TOTEM_FILE_END, TOTEM_FILE_MARKER, } from './init-templates.js';
30
+ import { hooksCommand, installHooksCommand, installHooksNonInteractive, regenerateManagedSessionHooks, resolveHooksDir, TOTEM_PREPUSH_END, TOTEM_PREPUSH_MARKER, } from './install-hooks.js';
31
+ // ─── Roster invariant (locked contract, mmnto-ai/totem#2410) ─────────
32
+ describe('MANAGED_SESSION_HOOKS roster invariant', () => {
33
+ it('every entry embeds its own marker AND end marker (so regenerated artifacts self-repair)', () => {
34
+ expect(MANAGED_SESSION_HOOKS.length).toBeGreaterThan(0);
35
+ for (const { rel, content, marker, endMarker } of MANAGED_SESSION_HOOKS) {
36
+ expect(content.includes(marker), `${rel} content is missing its marker`).toBe(true);
37
+ expect(content.includes(endMarker), `${rel} content is missing its end marker`).toBe(true);
38
+ // The marker must OPEN the file (only whitespace before it) — the ownership
39
+ // precondition for bounded drift-repair.
40
+ expect(content.trimStart().startsWith(marker), `${rel} marker must open the file`).toBe(true);
41
+ // The end marker must CLOSE the region (nothing but whitespace after it).
42
+ const endIdx = content.indexOf(endMarker);
43
+ expect(content.slice(endIdx + endMarker.length).trim()).toBe('');
44
+ }
45
+ });
46
+ it('covers the six distributed managed artifacts (incl. the PR-B prepare wrapper)', () => {
47
+ const rels = MANAGED_SESSION_HOOKS.map((h) => h.rel).sort();
48
+ expect(rels).toEqual([
49
+ '.claude/hooks/PreWriteShield.cjs',
50
+ '.claude/hooks/SessionStart.cjs',
51
+ '.claude/hooks/gate-wrapper.cjs',
52
+ '.gemini/hooks/BeforeTool.js',
53
+ '.gemini/hooks/SessionStart.js',
54
+ '.totem/prepare.cjs',
55
+ ].sort());
56
+ });
57
+ });
58
+ // ─── Managed session-hook bounded drift-repair (slice 3) ─────────────
59
+ describe('regenerateManagedSessionHooks — bounded drift-repair matrix', () => {
60
+ let tmpDir;
61
+ const CLAUDE_SS = '.claude/hooks/SessionStart.cjs';
62
+ function writeHook(rel, content) {
63
+ const p = path.join(tmpDir, ...rel.split('/'));
64
+ fs.mkdirSync(path.dirname(p), { recursive: true });
65
+ fs.writeFileSync(p, content, 'utf-8');
66
+ return p;
67
+ }
68
+ beforeEach(() => {
69
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-2410-sess-'));
70
+ });
71
+ afterEach(() => {
72
+ cleanTmpDir(tmpDir);
73
+ });
74
+ it('does NOT create a missing session hook (regenerate-only-if-present)', async () => {
75
+ const results = await regenerateManagedSessionHooks(tmpDir);
76
+ expect(results).toEqual([]);
77
+ expect(fs.existsSync(path.join(tmpDir, ...CLAUDE_SS.split('/')))).toBe(false);
78
+ });
79
+ it('returns exists for a present, byte-identical session hook (already current)', async () => {
80
+ writeHook(CLAUDE_SS, CLAUDE_SESSION_START);
81
+ const results = await regenerateManagedSessionHooks(tmpDir);
82
+ const r = results.find((x) => x.file === CLAUDE_SS);
83
+ expect(r.action).toBe('exists');
84
+ expect(fs.readFileSync(path.join(tmpDir, ...CLAUDE_SS.split('/')), 'utf-8')).toBe(CLAUDE_SESSION_START);
85
+ });
86
+ it('bare drift-repairs a bounded totem-owned session hook (overwritten, no force)', async () => {
87
+ const p = writeHook(CLAUDE_SS, `${TOTEM_FILE_MARKER}\nstale body\n${TOTEM_FILE_END}\n`);
88
+ const results = await regenerateManagedSessionHooks(tmpDir);
89
+ const r = results.find((x) => x.file === CLAUDE_SS);
90
+ expect(r.action).toBe('overwritten');
91
+ // Regenerated to canonical — and canonical carries marker + end marker.
92
+ const written = fs.readFileSync(p, 'utf-8');
93
+ expect(written).toBe(CLAUDE_SESSION_START);
94
+ expect(written.includes(TOTEM_FILE_MARKER)).toBe(true);
95
+ expect(written.includes(TOTEM_FILE_END)).toBe(true);
96
+ });
97
+ it('does NOT bare-repair a legacy marker-headed session hook missing the end marker', async () => {
98
+ const legacy = `${TOTEM_FILE_MARKER} — Claude Code SessionStart hook\nstale legacy body\n`;
99
+ const p = writeHook(CLAUDE_SS, legacy);
100
+ const results = await regenerateManagedSessionHooks(tmpDir);
101
+ const r = results.find((x) => x.file === CLAUDE_SS);
102
+ expect(r.action).toBe('declined');
103
+ // Untouched — takes one `totem hook install --force`.
104
+ expect(fs.readFileSync(p, 'utf-8')).toBe(legacy);
105
+ });
106
+ it('--force overwrites a legacy markerless-end session hook (the migration path)', async () => {
107
+ const legacy = `${TOTEM_FILE_MARKER} — Claude Code SessionStart hook\nstale legacy body\n`;
108
+ const p = writeHook(CLAUDE_SS, legacy);
109
+ const results = await regenerateManagedSessionHooks(tmpDir, true);
110
+ const r = results.find((x) => x.file === CLAUDE_SS);
111
+ expect(r.action).toBe('overwritten');
112
+ expect(fs.readFileSync(p, 'utf-8')).toBe(CLAUDE_SESSION_START);
113
+ });
114
+ it('does NOT repair a bounded hook with user content AFTER the end marker (bare declines)', async () => {
115
+ const withTrailingUser = `${TOTEM_FILE_MARKER}\nstale\n${TOTEM_FILE_END}\nconsole.log("mine");\n`;
116
+ const p = writeHook(CLAUDE_SS, withTrailingUser);
117
+ const results = await regenerateManagedSessionHooks(tmpDir);
118
+ expect(results.find((x) => x.file === CLAUDE_SS).action).toBe('declined');
119
+ expect(fs.readFileSync(p, 'utf-8')).toBe(withTrailingUser);
120
+ });
121
+ it('never touches a user-owned file with NO totem marker, even under --force (skipped)', async () => {
122
+ const userOwned = '// my own SessionStart hook\nconsole.log("mine");\n';
123
+ const p = writeHook(CLAUDE_SS, userOwned);
124
+ const bare = await regenerateManagedSessionHooks(tmpDir);
125
+ expect(bare.find((x) => x.file === CLAUDE_SS).action).toBe('skipped');
126
+ expect(fs.readFileSync(p, 'utf-8')).toBe(userOwned);
127
+ const forced = await regenerateManagedSessionHooks(tmpDir, true);
128
+ expect(forced.find((x) => x.file === CLAUDE_SS).action).toBe('skipped');
129
+ expect(fs.readFileSync(p, 'utf-8')).toBe(userOwned);
130
+ });
131
+ it('never touches a user file that merely QUOTES the marker (marker not at start), even under --force', async () => {
132
+ // A user-owned hook that quotes the marker string in a comment/string is NOT
133
+ // marker-headed (positional gate, mmnto-ai/totem#2413). The old `includes(marker)`
134
+ // gate would treat it as owned and let --force clobber it.
135
+ const quotesMarker = `// my own hook\n// I copied this line: ${TOTEM_FILE_MARKER}\nconsole.log("mine");\n`;
136
+ const p = writeHook(CLAUDE_SS, quotesMarker);
137
+ const bare = await regenerateManagedSessionHooks(tmpDir);
138
+ expect(bare.find((x) => x.file === CLAUDE_SS).action).toBe('skipped');
139
+ expect(fs.readFileSync(p, 'utf-8')).toBe(quotesMarker);
140
+ const forced = await regenerateManagedSessionHooks(tmpDir, true);
141
+ expect(forced.find((x) => x.file === CLAUDE_SS).action).toBe('skipped');
142
+ expect(fs.readFileSync(p, 'utf-8')).toBe(quotesMarker);
143
+ });
144
+ it('repairs each vendor family independently (claude + gemini)', async () => {
145
+ writeHook('.claude/hooks/PreWriteShield.cjs', `${TOTEM_FILE_MARKER}\nstale\n${TOTEM_FILE_END}\n`);
146
+ writeHook('.gemini/hooks/SessionStart.js', GEMINI_SESSION_START); // already current
147
+ const results = await regenerateManagedSessionHooks(tmpDir);
148
+ expect(results.find((x) => x.file === '.claude/hooks/PreWriteShield.cjs').action).toBe('overwritten');
149
+ expect(fs.readFileSync(path.join(tmpDir, '.claude', 'hooks', 'PreWriteShield.cjs'), 'utf-8')).toBe(CLAUDE_PREWRITESHIELD);
150
+ expect(results.find((x) => x.file === '.gemini/hooks/SessionStart.js').action).toBe('exists');
151
+ });
152
+ });
153
+ // ─── hooksCommand exit-code contract (slice 2) ───────────────────────
154
+ describe('hooksCommand exit-code contract', () => {
155
+ let tmpDir;
156
+ let originalCwd;
157
+ let errorSpy;
158
+ let exitSpy;
159
+ const hooksDir = () => path.join(tmpDir, '.git', 'hooks');
160
+ const errorOutput = () => errorSpy.mock.calls
161
+ .map((c) => c.map((a) => String(a)).join(' '))
162
+ .join('\n');
163
+ beforeEach(() => {
164
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-2410-cmd-'));
165
+ execSync('git init', { cwd: tmpDir, stdio: 'ignore' });
166
+ originalCwd = process.cwd();
167
+ process.chdir(tmpDir);
168
+ errorSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
169
+ // A throwing process.exit surfaces a --check failure as a rejection (the CLI
170
+ // edge would exit non-zero); the install path must never reach it.
171
+ exitSpy = vi.spyOn(process, 'exit').mockImplementation(((code) => {
172
+ throw new Error(`process.exit:${code ?? 0}`);
173
+ }));
174
+ });
175
+ afterEach(() => {
176
+ process.chdir(originalCwd);
177
+ vi.restoreAllMocks();
178
+ cleanTmpDir(tmpDir);
179
+ });
180
+ // ── exit 0 classes ──────────────────────────────────────────────
181
+ it('exit 0: fresh install (no throw, no process.exit)', async () => {
182
+ await expect(hooksCommand({})).resolves.toBeUndefined();
183
+ expect(exitSpy).not.toHaveBeenCalled();
184
+ expect(fs.existsSync(path.join(hooksDir(), 'pre-push'))).toBe(true);
185
+ });
186
+ it('exit 0: already-current (second install is a no-op)', async () => {
187
+ await hooksCommand({});
188
+ errorSpy.mockClear();
189
+ await expect(hooksCommand({})).resolves.toBeUndefined();
190
+ expect(exitSpy).not.toHaveBeenCalled();
191
+ expect(errorOutput()).toContain('already installed');
192
+ });
193
+ it('exit 0: bare git-hook drift-repair prints "Drift-repaired", not "Force-overwritten"', async () => {
194
+ await hooksCommand({});
195
+ // Corrupt pre-push to a stale-but-bounded totem-owned whole file.
196
+ fs.writeFileSync(path.join(hooksDir(), 'pre-push'), `#!/bin/sh\n# ${TOTEM_PREPUSH_MARKER}\nstale\n# ${TOTEM_PREPUSH_END}\n`);
197
+ errorSpy.mockClear();
198
+ await expect(hooksCommand({})).resolves.toBeUndefined();
199
+ expect(exitSpy).not.toHaveBeenCalled();
200
+ const out = errorOutput();
201
+ expect(out).toContain('Drift-repaired pre-push hook (totem-owned bounded region).');
202
+ expect(out).not.toContain('Force-overwritten pre-push');
203
+ });
204
+ it('exit 0: bare session-hook drift-repair prints "Drift-repaired"', async () => {
205
+ fs.mkdirSync(path.join(tmpDir, '.claude', 'hooks'), { recursive: true });
206
+ fs.writeFileSync(path.join(tmpDir, '.claude', 'hooks', 'SessionStart.cjs'), `${TOTEM_FILE_MARKER}\nstale\n${TOTEM_FILE_END}\n`);
207
+ errorSpy.mockClear();
208
+ await expect(hooksCommand({})).resolves.toBeUndefined();
209
+ expect(exitSpy).not.toHaveBeenCalled();
210
+ expect(errorOutput()).toContain('Drift-repaired .claude/hooks/SessionStart.cjs session hook (totem-owned bounded region).');
211
+ expect(fs.readFileSync(path.join(tmpDir, '.claude', 'hooks', 'SessionStart.cjs'), 'utf-8')).toBe(CLAUDE_SESSION_START);
212
+ });
213
+ it('exit 0: declared skip — not a git repository', async () => {
214
+ const nonGit = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-2410-nogit-'));
215
+ process.chdir(nonGit);
216
+ try {
217
+ await expect(hooksCommand({})).resolves.toBeUndefined();
218
+ expect(exitSpy).not.toHaveBeenCalled();
219
+ expect(errorOutput()).toContain('Not a git repository');
220
+ }
221
+ finally {
222
+ process.chdir(tmpDir);
223
+ cleanTmpDir(nonGit);
224
+ }
225
+ });
226
+ it('exit 0: declared skip — hook manager detected', async () => {
227
+ fs.mkdirSync(path.join(tmpDir, '.husky'), { recursive: true });
228
+ await expect(hooksCommand({})).resolves.toBeUndefined();
229
+ expect(exitSpy).not.toHaveBeenCalled();
230
+ });
231
+ it('file-valued core.hooksPath: declares the git-hook skip, session hooks STILL repaired (exit 0)', async () => {
232
+ // CR #2422 round 2 falsifier: an unresolvable hooks dir (core.hooksPath at a
233
+ // non-directory — the hooks-disabled idiom) skips GIT hook installation with
234
+ // the truthful scoped line, while the managed session hooks — vendor
235
+ // artifacts independent of git-hook state (PR-A slice 3 / lc#806) — are
236
+ // still drift-repaired. Continuing past the git-hook skip is the contract,
237
+ // not a leak.
238
+ const notADir = path.join(tmpDir, 'hooks-disabled.txt');
239
+ fs.writeFileSync(notADir, 'not a directory\n');
240
+ execFileSync('git', ['config', 'core.hooksPath', notADir], { cwd: tmpDir });
241
+ const ssPath = path.join(tmpDir, '.claude', 'hooks', 'SessionStart.cjs');
242
+ fs.mkdirSync(path.dirname(ssPath), { recursive: true });
243
+ fs.writeFileSync(ssPath, `${TOTEM_FILE_MARKER}\nstale\n${TOTEM_FILE_END}\n`);
244
+ errorSpy.mockClear();
245
+ await expect(hooksCommand({})).resolves.toBeUndefined();
246
+ expect(exitSpy).not.toHaveBeenCalled();
247
+ expect(errorOutput()).toContain('skipping git hook installation');
248
+ // The non-directory target never receives a write.
249
+ expect(fs.readFileSync(notADir, 'utf-8')).toBe('not a directory\n');
250
+ // The bounded session hook is still repaired after the git-hook skip.
251
+ expect(fs.readFileSync(ssPath, 'utf-8')).toBe(CLAUDE_SESSION_START);
252
+ });
253
+ it('hook-manager repo STILL drift-repairs an existing bounded session hook (lc#806 guard)', async () => {
254
+ // A git-hook manager (husky) means git hooks are the manager's job — a declared
255
+ // skip for the git side. But the session hooks are Claude/Gemini artifacts,
256
+ // independent of the manager, so they must still be regenerated: the fix for the
257
+ // hook-manager early-return that otherwise recreates the lc#806 stale class.
258
+ fs.mkdirSync(path.join(tmpDir, '.husky'), { recursive: true });
259
+ const ssPath = path.join(tmpDir, '.claude', 'hooks', 'SessionStart.cjs');
260
+ fs.mkdirSync(path.dirname(ssPath), { recursive: true });
261
+ fs.writeFileSync(ssPath, `${TOTEM_FILE_MARKER}\nstale\n${TOTEM_FILE_END}\n`);
262
+ errorSpy.mockClear();
263
+ await expect(hooksCommand({})).resolves.toBeUndefined();
264
+ expect(exitSpy).not.toHaveBeenCalled();
265
+ // The bounded session hook is drift-repaired even though git hooks were skipped.
266
+ expect(fs.readFileSync(ssPath, 'utf-8')).toBe(CLAUDE_SESSION_START);
267
+ expect(errorOutput()).toContain('Drift-repaired .claude/hooks/SessionStart.cjs session hook (totem-owned bounded region).');
268
+ });
269
+ // ── exit ≠0: genuine failure ────────────────────────────────────
270
+ it('exit ≠0: a genuine hook-write failure propagates as a thrown error', async () => {
271
+ // Make the first-installed hook PATH a directory: the installer's read/write of it
272
+ // throws EISDIR — a genuine FS failure that must PROPAGATE (fail-loud, Tenet 4),
273
+ // not be swallowed into a false `installed`. (A directory-at-path fault is
274
+ // cross-platform, unlike an ESM fs spy — vitest cannot redefine fs namespace exports.)
275
+ fs.mkdirSync(path.join(hooksDir(), 'pre-commit'), { recursive: true });
276
+ await expect(hooksCommand({})).rejects.toThrow();
277
+ expect(exitSpy).not.toHaveBeenCalled();
278
+ });
279
+ // ── --check: exactly 0/1 ────────────────────────────────────────
280
+ it('--check exit 0: all hooks present with markers', async () => {
281
+ await hooksCommand({});
282
+ errorSpy.mockClear();
283
+ await expect(hooksCommand({ check: true })).resolves.toBeUndefined();
284
+ expect(exitSpy).not.toHaveBeenCalled();
285
+ expect(errorOutput()).toContain('All hooks installed');
286
+ });
287
+ it('--check exit 1: hooks missing (and the remedy names `totem hook install`)', async () => {
288
+ await expect(hooksCommand({ check: true })).rejects.toThrow('process.exit:1');
289
+ expect(exitSpy).toHaveBeenCalledWith(1);
290
+ const out = errorOutput();
291
+ expect(out).toContain('Some hooks are missing');
292
+ expect(out).toContain('totem hook install');
293
+ expect(out).not.toContain('Run `totem hooks`');
294
+ });
295
+ it('--check exit 1: hook present but missing the Totem marker', async () => {
296
+ // Install, then strip the marker from one hook (markerless → not counted).
297
+ await hooksCommand({});
298
+ fs.writeFileSync(path.join(hooksDir(), 'pre-push'), '#!/bin/sh\necho "no marker"\n');
299
+ await expect(hooksCommand({ check: true })).rejects.toThrow('process.exit:1');
300
+ expect(exitSpy).toHaveBeenCalledWith(1);
301
+ });
302
+ it('--check is read-only: it does NOT mutate a drifted session hook', async () => {
303
+ // Install git hooks so --check passes on the git side (exit 0), then plant a
304
+ // drifted-but-bounded session hook. --check is a verify-only path and returns
305
+ // before session-hook regeneration, so the drifted hook must be left untouched.
306
+ await hooksCommand({});
307
+ const ssPath = path.join(tmpDir, '.claude', 'hooks', 'SessionStart.cjs');
308
+ fs.mkdirSync(path.dirname(ssPath), { recursive: true });
309
+ const drifted = `${TOTEM_FILE_MARKER}\nstale\n${TOTEM_FILE_END}\n`;
310
+ fs.writeFileSync(ssPath, drifted);
311
+ await expect(hooksCommand({ check: true })).resolves.toBeUndefined();
312
+ expect(exitSpy).not.toHaveBeenCalled();
313
+ expect(fs.readFileSync(ssPath, 'utf-8')).toBe(drifted);
314
+ });
315
+ // ── the two `overwritten` messages are distinct ─────────────────
316
+ it('bare drift-repair and --force overwrite print DISTINCT messages', async () => {
317
+ await hooksCommand({});
318
+ const staleBounded = `#!/bin/sh\n# ${TOTEM_PREPUSH_MARKER}\nstale\n# ${TOTEM_PREPUSH_END}\n`;
319
+ // Bare (no --force) bounded drift-repair.
320
+ fs.writeFileSync(path.join(hooksDir(), 'pre-push'), staleBounded);
321
+ errorSpy.mockClear();
322
+ await hooksCommand({});
323
+ const bareMsg = errorOutput()
324
+ .split('\n')
325
+ .find((l) => l.includes('pre-push hook'));
326
+ // --force overwrite of the same stale-bounded file.
327
+ fs.writeFileSync(path.join(hooksDir(), 'pre-push'), staleBounded);
328
+ errorSpy.mockClear();
329
+ await hooksCommand({ force: true });
330
+ const forceMsg = errorOutput()
331
+ .split('\n')
332
+ .find((l) => l.includes('pre-push hook'));
333
+ expect(bareMsg).toContain('Drift-repaired');
334
+ expect(forceMsg).toContain('Force-overwritten');
335
+ expect(bareMsg).not.toBe(forceMsg);
336
+ });
337
+ // ── bare install never mutates a non-bounded git hook ───────────
338
+ it('bare install never mutates a user hook with an appended totem block (non-bounded)', async () => {
339
+ const userThenTotem = `#!/bin/sh\nrun_my_tests\n# ${TOTEM_PREPUSH_MARKER}\nstale\n# ${TOTEM_PREPUSH_END}\n`;
340
+ fs.mkdirSync(hooksDir(), { recursive: true });
341
+ fs.writeFileSync(path.join(hooksDir(), 'pre-push'), userThenTotem);
342
+ await expect(hooksCommand({})).resolves.toBeUndefined();
343
+ expect(exitSpy).not.toHaveBeenCalled();
344
+ // User content preserved — only --force may overwrite an unbounded file.
345
+ expect(fs.readFileSync(path.join(hooksDir(), 'pre-push'), 'utf-8')).toBe(userThenTotem);
346
+ });
347
+ });
348
+ // ─── sanity: installHooksNonInteractive still classifies a fresh repo ─
349
+ describe('installHooksNonInteractive (contract sanity)', () => {
350
+ let tmpDir;
351
+ beforeEach(() => {
352
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-2410-ni-'));
353
+ });
354
+ afterEach(() => {
355
+ cleanTmpDir(tmpDir);
356
+ });
357
+ it('returns null outside a git repo (declared skip, exit 0 at the command edge)', () => {
358
+ expect(installHooksNonInteractive(tmpDir)).toBeNull();
359
+ });
360
+ });
361
+ // ─── Worktree + gitdir-pointer resolution (mmnto-ai/totem#2418) ──────
362
+ //
363
+ // In a linked worktree `.git` is a FILE (`gitdir: <path>` pointer), so the
364
+ // pre-fix blind `mkdir '.git/hooks'` crashed ENOTDIR and failed the consumer's
365
+ // whole `pnpm install` through the prepare wrapper. The contract names the
366
+ // worktree/submodule pointer cases: resolvable → install into the SHARED hooks
367
+ // dir (what git actually executes); unparseable → declared skip, exit 0.
368
+ describe('hooksCommand in a linked worktree (mmnto-ai/totem#2418)', () => {
369
+ let mainDir;
370
+ let wtParent;
371
+ let wtDir;
372
+ let originalCwd;
373
+ let errorSpy;
374
+ let exitSpy;
375
+ const sharedHooksDir = () => path.join(mainDir, '.git', 'hooks');
376
+ const errorOutput = () => errorSpy.mock.calls
377
+ .map((c) => c.map((a) => String(a)).join(' '))
378
+ .join('\n');
379
+ beforeEach(() => {
380
+ mainDir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-2418-main-'));
381
+ execSync('git init', { cwd: mainDir, stdio: 'ignore' });
382
+ // `git worktree add` needs a commit to branch from.
383
+ execSync('git -c user.name=totem -c user.email=totem@test.invalid commit --allow-empty -m init', { cwd: mainDir, stdio: 'ignore' });
384
+ wtParent = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-2418-wt-'));
385
+ wtDir = path.join(wtParent, 'wt');
386
+ // Arg-array spawn — no shell, so the tmp path is never shell-interpreted.
387
+ execFileSync('git', ['worktree', 'add', wtDir], { cwd: mainDir, stdio: 'ignore' });
388
+ originalCwd = process.cwd();
389
+ process.chdir(wtDir);
390
+ errorSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
391
+ exitSpy = vi.spyOn(process, 'exit').mockImplementation(((code) => {
392
+ throw new Error(`process.exit:${code ?? 0}`);
393
+ }));
394
+ });
395
+ afterEach(() => {
396
+ process.chdir(originalCwd);
397
+ vi.restoreAllMocks();
398
+ cleanTmpDir(wtParent);
399
+ cleanTmpDir(mainDir);
400
+ });
401
+ it('resolveHooksDir follows the gitdir pointer to the SHARED hooks dir', () => {
402
+ // The worktree's `.git` is a pointer FILE, not a directory.
403
+ expect(fs.statSync(path.join(wtDir, '.git')).isFile()).toBe(true);
404
+ const resolved = resolveHooksDir(wtDir);
405
+ expect(resolved).not.toBeNull();
406
+ // realpathSync.native both sides: git prints the LONG form while os.tmpdir()
407
+ // can carry a Windows 8.3 alias (RUNNER~1 on GH runners) or a symlinked
408
+ // tmpdir (macOS /var → /private/var); only the native variant expands both.
409
+ expect(fs.realpathSync.native(resolved)).toBe(fs.realpathSync.native(sharedHooksDir()));
410
+ });
411
+ it('resolveHooksDir in a plain checkout stays .git/hooks', () => {
412
+ const resolved = resolveHooksDir(mainDir);
413
+ expect(resolved).not.toBeNull();
414
+ expect(fs.realpathSync.native(resolved)).toBe(fs.realpathSync.native(sharedHooksDir()));
415
+ });
416
+ it('exit 0: install from the worktree lands in the shared hooks dir (no ENOTDIR)', async () => {
417
+ await expect(hooksCommand({})).resolves.toBeUndefined();
418
+ expect(exitSpy).not.toHaveBeenCalled();
419
+ for (const hook of ['pre-commit', 'pre-push', 'post-merge', 'post-checkout']) {
420
+ expect(fs.existsSync(path.join(sharedHooksDir(), hook)), `${hook} missing from the shared hooks dir`).toBe(true);
421
+ }
422
+ // The pointer file survives untouched — nothing tried to mkdir through it.
423
+ expect(fs.statSync(path.join(wtDir, '.git')).isFile()).toBe(true);
424
+ });
425
+ it('--check from the worktree sees the shared hooks (exit 0)', async () => {
426
+ await hooksCommand({});
427
+ errorSpy.mockClear();
428
+ await expect(hooksCommand({ check: true })).resolves.toBeUndefined();
429
+ expect(exitSpy).not.toHaveBeenCalled();
430
+ expect(errorOutput()).toContain('All hooks installed');
431
+ });
432
+ it('installHooksNonInteractive from the worktree classifies all four hooks', () => {
433
+ const result = installHooksNonInteractive(wtDir);
434
+ expect(result).not.toBeNull();
435
+ expect(result.preCommit).toBe('installed');
436
+ expect(result.prePush).toBe('installed');
437
+ expect(result.postMerge).toBe('installed');
438
+ expect(result.postCheckout).toBe('installed');
439
+ });
440
+ });
441
+ describe('hooksCommand with an unparseable .git pointer file (declared skip)', () => {
442
+ let tmpDir;
443
+ let originalCwd;
444
+ let errorSpy;
445
+ let exitSpy;
446
+ beforeEach(() => {
447
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-2418-badptr-'));
448
+ // A `.git` FILE whose content is not a `gitdir:` pointer — git reports
449
+ // `fatal: invalid gitfile format` for it.
450
+ fs.writeFileSync(path.join(tmpDir, '.git'), 'not a gitdir pointer\n');
451
+ originalCwd = process.cwd();
452
+ process.chdir(tmpDir);
453
+ errorSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
454
+ exitSpy = vi.spyOn(process, 'exit').mockImplementation(((code) => {
455
+ throw new Error(`process.exit:${code ?? 0}`);
456
+ }));
457
+ });
458
+ afterEach(() => {
459
+ process.chdir(originalCwd);
460
+ vi.restoreAllMocks();
461
+ cleanTmpDir(tmpDir);
462
+ });
463
+ it('exit 0: install declares the skip instead of crashing prepare', async () => {
464
+ await expect(hooksCommand({})).resolves.toBeUndefined();
465
+ expect(exitSpy).not.toHaveBeenCalled();
466
+ const out = errorSpy.mock.calls
467
+ .map((c) => c.map((a) => String(a)).join(' '))
468
+ .join('\n');
469
+ expect(out).toContain('not a directory or a resolvable gitdir pointer');
470
+ });
471
+ it('resolveHooksDir returns null for the unparseable pointer (never a blind join)', () => {
472
+ expect(resolveHooksDir(tmpDir)).toBeNull();
473
+ });
474
+ it('legacy installHooksCommand declares the skip too — exit 0, never handleError (#2422 round)', async () => {
475
+ // The hidden `totem install-hooks` command routes here; pre-fix its callees
476
+ // let the resolveGitRoot throw reach handleError → exit 1, violating the
477
+ // #2410 declared-skip contract on that entry point.
478
+ await expect(installHooksCommand()).resolves.toBeUndefined();
479
+ expect(exitSpy).not.toHaveBeenCalled();
480
+ const out = errorSpy.mock.calls
481
+ .map((c) => c.map((a) => String(a)).join(' '))
482
+ .join('\n');
483
+ expect(out).toContain('not a directory or a resolvable gitdir pointer');
484
+ });
485
+ it('installHooksNonInteractive maps the bad pointer to the declared-skip null (direct API path)', () => {
486
+ expect(installHooksNonInteractive(tmpDir)).toBeNull();
487
+ });
488
+ });
489
+ describe('resolveHooksDir with core.hooksPath aimed at a non-directory (#2422 round)', () => {
490
+ let tmpDir;
491
+ beforeEach(() => {
492
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-2418-hookspath-'));
493
+ execSync('git init', { cwd: tmpDir, stdio: 'ignore' });
494
+ });
495
+ afterEach(() => {
496
+ cleanTmpDir(tmpDir);
497
+ });
498
+ it('returns null instead of a write-target that can never receive hooks', () => {
499
+ // The /dev/null hooks-disabled idiom, portably: point core.hooksPath at an
500
+ // existing FILE. `git rev-parse --git-path hooks` returns it verbatim; the
501
+ // resolver must classify it as the declared skip, not hand it to mkdir.
502
+ const notADir = path.join(tmpDir, 'hooks-disabled.txt');
503
+ fs.writeFileSync(notADir, 'not a directory\n');
504
+ execFileSync('git', ['config', 'core.hooksPath', notADir], { cwd: tmpDir });
505
+ expect(resolveHooksDir(tmpDir)).toBeNull();
506
+ });
507
+ });
508
+ //# sourceMappingURL=install-hooks-exit-contract.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-hooks-exit-contract.test.js","sourceRoot":"","sources":["../../src/commands/install-hooks-exit-contract.test.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,20 @@ export declare const TOTEM_PRECOMMIT_MARKER = "[totem] pre-commit hook";
7
7
  export declare const TOTEM_PRECOMMIT_END = "[totem] end pre-commit";
8
8
  export declare const TOTEM_PREPUSH_MARKER = "[totem] pre-push hook";
9
9
  export declare const TOTEM_PREPUSH_END = "[totem] end pre-push";
10
+ /**
11
+ * Resolve the git hooks directory for `gitRoot`. In a plain checkout this is
12
+ * `.git/hooks`, but in a linked worktree (or submodule) `.git` is a FILE
13
+ * (`gitdir: <path>` pointer) and hooks live under the resolved git dir — shared
14
+ * across worktrees via `commondir` — so a blind `.git/hooks` join makes
15
+ * `mkdirSync` crash with ENOTDIR (mmnto-ai/totem#2418; the owner-repo
16
+ * `tools/install-hooks.js` variant already discriminates). Resolution is
17
+ * delegated to `git rev-parse --git-path hooks` — git's own worktree/commondir
18
+ * walk, which also honors `core.hooksPath` — with a filesystem probe as the
19
+ * offline fallback for the plain-directory layout. Returns null when no hooks
20
+ * directory can be resolved: the #2410 declared-skip class — callers skip
21
+ * loudly instead of guessing a path.
22
+ */
23
+ export declare function resolveHooksDir(gitRoot: string): string | null;
10
24
  /**
11
25
  * Determine the package-manager fallback command for invoking totem.
12
26
  * Used inside the runtime resolve block when `totem` is not on PATH.
@@ -99,6 +113,45 @@ export declare function hooksCommand(opts: {
99
113
  strict?: boolean;
100
114
  standard?: boolean;
101
115
  }): Promise<void>;
116
+ /**
117
+ * The action taken on one managed session-hook artifact by
118
+ * {@link regenerateManagedSessionHooks}:
119
+ * - `exists` — present, marker-headed, already byte-identical to canonical (no write).
120
+ * - `overwritten` — regenerated: a bare bounded drift-repair OR a `--force` overwrite.
121
+ * - `declined` — marker present but the region is NOT bounded-owned (legacy file
122
+ * with no end marker, or user content after the end marker) and no
123
+ * `--force`: left untouched, takes one `totem hook install --force`.
124
+ * - `skipped` — a user-owned file carrying NO totem marker at all: never touched,
125
+ * not even under `--force`.
126
+ */
127
+ export type ManagedSessionHookAction = 'exists' | 'overwritten' | 'declined' | 'skipped';
128
+ export interface ManagedSessionHookResult {
129
+ /** Repo-relative path of the artifact. */
130
+ file: string;
131
+ action: ManagedSessionHookAction;
132
+ }
133
+ /**
134
+ * Walk the {@link MANAGED_SESSION_HOOKS} roster and regenerate the whole-file
135
+ * session-hook artifacts (`.claude/hooks/*.cjs`, `.gemini/hooks/*.js`) that EXIST
136
+ * under `cwd`, applying the #2406 bounded-ownership semantics generalized to the
137
+ * JS/CJS hook family:
138
+ *
139
+ * - Missing file → not created (creation is `totem init`'s job); omitted
140
+ * from the results entirely.
141
+ * - Marker + identical → `exists` (already current).
142
+ * - Marker + drifted, bounded totem-owned whole file → bare drift-repair
143
+ * (`overwritten`), or `--force` → `overwritten`.
144
+ * - Marker + drifted, unbounded (legacy no-end-marker / trailing user content):
145
+ * bare → `declined`; `--force` → `overwritten`.
146
+ * - Marker does not OPEN the file (no marker, or a merely-quoted marker) →
147
+ * `skipped` even under `--force` (never clobber a
148
+ * user-owned file).
149
+ *
150
+ * Regenerate-only-if-present, single-writer per invocation. A write failure
151
+ * (perms/FS) PROPAGATES (Tenet 4 — a hook the tool cannot write must fail loud,
152
+ * never silently report success), mirroring `installGitHook`.
153
+ */
154
+ export declare function regenerateManagedSessionHooks(cwd: string, force?: boolean): Promise<ManagedSessionHookResult[]>;
102
155
  /**
103
156
  * Silently upgrade the pre-push hook if it was installed by Totem but uses
104
157
  * an old format (flag-checking or command-executing) instead of the new
@@ -1 +1 @@
1
- {"version":3,"file":"install-hooks.d.ts","sourceRoot":"","sources":["../../src/commands/install-hooks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"install-hooks.d.ts","sourceRoot":"","sources":["../../src/commands/install-hooks.ts"],"names":[],"mappings":"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"}