@mmnto/cli 1.103.0 → 1.104.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.
- package/dist/commands/doctor-parity-fetch.d.ts +84 -0
- package/dist/commands/doctor-parity-fetch.d.ts.map +1 -0
- package/dist/commands/doctor-parity-fetch.js +367 -0
- package/dist/commands/doctor-parity-fetch.js.map +1 -0
- package/dist/commands/doctor-parity-fetch.test.d.ts +13 -0
- package/dist/commands/doctor-parity-fetch.test.d.ts.map +1 -0
- package/dist/commands/doctor-parity-fetch.test.js +269 -0
- package/dist/commands/doctor-parity-fetch.test.js.map +1 -0
- package/dist/commands/doctor-parity.d.ts.map +1 -1
- package/dist/commands/doctor-parity.js +57 -1
- package/dist/commands/doctor-parity.js.map +1 -1
- package/dist/commands/eject.d.ts.map +1 -1
- package/dist/commands/eject.js +3 -0
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/init-templates.d.ts +15 -0
- package/dist/commands/init-templates.d.ts.map +1 -1
- package/dist/commands/init-templates.js +183 -2
- package/dist/commands/init-templates.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +30 -2
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/init.test.js +264 -1
- package/dist/commands/init.test.js.map +1 -1
- package/dist/commands/install-hooks-exit-contract.test.js +107 -3
- package/dist/commands/install-hooks-exit-contract.test.js.map +1 -1
- package/dist/commands/install-hooks.d.ts +39 -0
- package/dist/commands/install-hooks.d.ts.map +1 -1
- package/dist/commands/install-hooks.js +152 -0
- package/dist/commands/install-hooks.js.map +1 -1
- package/dist/commands/pr.d.ts +130 -0
- package/dist/commands/pr.d.ts.map +1 -0
- package/dist/commands/pr.js +427 -0
- package/dist/commands/pr.js.map +1 -0
- package/dist/commands/pr.test.d.ts +2 -0
- package/dist/commands/pr.test.d.ts.map +1 -0
- package/dist/commands/pr.test.js +494 -0
- package/dist/commands/pr.test.js.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { assertValidPrNumberArg, buildIssueCloseArgv, buildMergeArgv, displayGhCommand, evaluatePrMerge, FORBIDDEN_MERGE_FLAGS, prMergeCommand, } from './pr.js';
|
|
3
|
+
const CONFORMING_POSTURE = {
|
|
4
|
+
squashMergeAllowed: true,
|
|
5
|
+
mergeCommitAllowed: false,
|
|
6
|
+
rebaseMergeAllowed: false,
|
|
7
|
+
squashMergeCommitTitle: 'PR_TITLE',
|
|
8
|
+
squashMergeCommitMessage: 'BLANK',
|
|
9
|
+
};
|
|
10
|
+
function makeHarness(cfg = {}) {
|
|
11
|
+
const calls = [];
|
|
12
|
+
// Accumulate the captured streams verbatim (each write() chunk carries its own
|
|
13
|
+
// newlines) — a running concat reconstructs the stream exactly.
|
|
14
|
+
let outStr = '';
|
|
15
|
+
let errStr = '';
|
|
16
|
+
const repo = cfg.repo ?? 'mmnto-ai/totem';
|
|
17
|
+
const posture = cfg.posture ?? CONFORMING_POSTURE;
|
|
18
|
+
const mergedState = cfg.mergedState ?? 'MERGED';
|
|
19
|
+
const pr = cfg.pr ?? {
|
|
20
|
+
title: 'feat: a clean title',
|
|
21
|
+
body: 'A body with no close keywords. references #9.',
|
|
22
|
+
state: 'OPEN',
|
|
23
|
+
number: 5,
|
|
24
|
+
headRefOid: 'deadbeef',
|
|
25
|
+
};
|
|
26
|
+
const gh = (args) => {
|
|
27
|
+
calls.push(args);
|
|
28
|
+
const thrown = cfg.throwOn?.(args);
|
|
29
|
+
if (thrown)
|
|
30
|
+
throw thrown;
|
|
31
|
+
if (args[0] === 'repo' && args[1] === 'view')
|
|
32
|
+
return `${repo}\n`;
|
|
33
|
+
if (args[0] === 'api' && args[1] === 'graphql')
|
|
34
|
+
return JSON.stringify(posture);
|
|
35
|
+
if (args[0] === 'pr' && args[1] === 'view') {
|
|
36
|
+
// Two `pr view` shapes: the pre-merge fetch (title,body,…) and the
|
|
37
|
+
// post-merge landing-state re-read (--json state,mergedAt).
|
|
38
|
+
if (args.includes('state,mergedAt')) {
|
|
39
|
+
return JSON.stringify({
|
|
40
|
+
state: mergedState,
|
|
41
|
+
mergedAt: mergedState === 'MERGED' ? '2026-07-21T00:00:00Z' : null,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return JSON.stringify(pr);
|
|
45
|
+
}
|
|
46
|
+
return '';
|
|
47
|
+
};
|
|
48
|
+
const deps = {
|
|
49
|
+
gh,
|
|
50
|
+
cwd: '/repo',
|
|
51
|
+
out: (t) => {
|
|
52
|
+
outStr += t;
|
|
53
|
+
},
|
|
54
|
+
err: (t) => {
|
|
55
|
+
errStr += t;
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
const mergeCalled = () => calls.some((a) => a[0] === 'pr' && a[1] === 'merge');
|
|
59
|
+
const issueCloseCalls = () => calls.filter((a) => a[0] === 'issue' && a[1] === 'close');
|
|
60
|
+
return {
|
|
61
|
+
deps,
|
|
62
|
+
calls,
|
|
63
|
+
mergeCalled,
|
|
64
|
+
issueCloseCalls,
|
|
65
|
+
out: () => outStr,
|
|
66
|
+
err: () => errStr,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
describe('buildMergeArgv (structural — NO body/subject flags; repo + head-bound)', () => {
|
|
70
|
+
it('is `pr merge <n> --repo <r> --squash --match-head-commit <oid>`', () => {
|
|
71
|
+
expect(buildMergeArgv(5, 'mmnto-ai/totem', 'deadbeef')).toEqual([
|
|
72
|
+
'pr',
|
|
73
|
+
'merge',
|
|
74
|
+
'5',
|
|
75
|
+
'--repo',
|
|
76
|
+
'mmnto-ai/totem',
|
|
77
|
+
'--squash',
|
|
78
|
+
'--match-head-commit',
|
|
79
|
+
'deadbeef',
|
|
80
|
+
]);
|
|
81
|
+
});
|
|
82
|
+
it('never contains any forbidden body/subject flag; DOES bind --match-head-commit', () => {
|
|
83
|
+
for (const n of [1, 42, 1762, 999999]) {
|
|
84
|
+
const argv = buildMergeArgv(n, 'o/r', 'sha123');
|
|
85
|
+
for (const flag of FORBIDDEN_MERGE_FLAGS) {
|
|
86
|
+
expect(argv).not.toContain(flag);
|
|
87
|
+
}
|
|
88
|
+
// Squash-only; never a non-squash merge method.
|
|
89
|
+
expect(argv).toContain('--squash');
|
|
90
|
+
expect(argv).not.toContain('--merge');
|
|
91
|
+
expect(argv).not.toContain('--rebase');
|
|
92
|
+
// Snapshot binding (codex Q): the evaluated head is pinned.
|
|
93
|
+
expect(argv).toContain('--match-head-commit');
|
|
94
|
+
expect(argv[argv.indexOf('--match-head-commit') + 1]).toBe('sha123');
|
|
95
|
+
// Repo binding (codex B-2): same identity the lookup used.
|
|
96
|
+
expect(argv).toContain('--repo');
|
|
97
|
+
expect(argv[argv.indexOf('--repo') + 1]).toBe('o/r');
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
describe('buildIssueCloseArgv', () => {
|
|
102
|
+
it('binds a bare ref to the resolved repo with a PR-naming comment', () => {
|
|
103
|
+
const argv = buildIssueCloseArgv({ issue: 42 }, 5, 'mmnto-ai/totem');
|
|
104
|
+
expect(argv.slice(0, 3)).toEqual(['issue', 'close', '42']);
|
|
105
|
+
expect(argv).toContain('--repo');
|
|
106
|
+
expect(argv[argv.indexOf('--repo') + 1]).toBe('mmnto-ai/totem');
|
|
107
|
+
const comment = argv[argv.indexOf('--comment') + 1];
|
|
108
|
+
expect(comment).toContain('#5');
|
|
109
|
+
});
|
|
110
|
+
it('uses the qualifier repo for a cross-repo qualified ref', () => {
|
|
111
|
+
const argv = buildIssueCloseArgv({ qualifier: 'mmnto-ai/totem-strategy', issue: 7 }, 5, 'o/r');
|
|
112
|
+
expect(argv[argv.indexOf('--repo') + 1]).toBe('mmnto-ai/totem-strategy');
|
|
113
|
+
});
|
|
114
|
+
it('the close comment carries no close-keyword adjacent to the digit ref', () => {
|
|
115
|
+
const comment = buildIssueCloseArgv({ issue: 42 }, 5, 'o/r').at(-1) ?? '';
|
|
116
|
+
// The word immediately before the #N ref must not be a close keyword.
|
|
117
|
+
expect(comment).not.toMatch(/\b(?:closes?d?|fix(?:e[sd])?|resolve[sd]?)\s+#\d/i);
|
|
118
|
+
});
|
|
119
|
+
it('the close comment carries NO backticks (paste-safe — codex NB-1)', () => {
|
|
120
|
+
const comment = buildIssueCloseArgv({ issue: 42 }, 5, 'o/r').at(-1) ?? '';
|
|
121
|
+
expect(comment).not.toContain('`');
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
describe('assertValidPrNumberArg (confused-deputy guard — codex B-2)', () => {
|
|
125
|
+
it('accepts undefined (merge the current branch PR) and a positive decimal', () => {
|
|
126
|
+
expect(() => assertValidPrNumberArg(undefined)).not.toThrow();
|
|
127
|
+
expect(() => assertValidPrNumberArg('1762')).not.toThrow();
|
|
128
|
+
});
|
|
129
|
+
it('rejects a URL positional (the confused-deputy vector)', () => {
|
|
130
|
+
expect(() => assertValidPrNumberArg('https://github.com/other/repo/pull/5')).toThrow(/invalid PR argument/i);
|
|
131
|
+
});
|
|
132
|
+
it('rejects a branch name, a zero, and a leading-zero form', () => {
|
|
133
|
+
expect(() => assertValidPrNumberArg('feature/x')).toThrow();
|
|
134
|
+
expect(() => assertValidPrNumberArg('0')).toThrow();
|
|
135
|
+
expect(() => assertValidPrNumberArg('007')).toThrow();
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
describe('displayGhCommand (paste-safe rendering — codex NB-1)', () => {
|
|
139
|
+
it('quotes the multi-word comment arg and never emits a bare #N or backtick', () => {
|
|
140
|
+
const line = displayGhCommand(buildIssueCloseArgv({ issue: 55 }, 5, 'o/r'));
|
|
141
|
+
expect(line.startsWith('gh issue close 55 --repo o/r --comment ')).toBe(true);
|
|
142
|
+
expect(line).not.toContain('`');
|
|
143
|
+
// The comment (with spaces + #N) must be a single quoted token, not bare.
|
|
144
|
+
expect(line).toMatch(/--comment '.*#5.*'/);
|
|
145
|
+
// No unquoted `#5` sitting outside quotes (would truncate as a shell comment).
|
|
146
|
+
expect(line).not.toMatch(/[^']#5(?![^']*')/);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
describe('evaluatePrMerge (pure — reuses the ONE shared evaluator)', () => {
|
|
150
|
+
const repo = 'mmnto-ai/totem';
|
|
151
|
+
it('is clean for a body with no close-keyword refs', () => {
|
|
152
|
+
const e = evaluatePrMerge({ title: 'feat: x', body: 'references #9, see #10', repo });
|
|
153
|
+
expect(e.ok).toBe(true);
|
|
154
|
+
expect(e.undeclared).toEqual([]);
|
|
155
|
+
});
|
|
156
|
+
it('flags a genuine close keyword', () => {
|
|
157
|
+
const e = evaluatePrMerge({ title: 'feat: x', body: 'Fixes #700', repo });
|
|
158
|
+
expect(e.ok).toBe(false);
|
|
159
|
+
expect(e.undeclared).toContain('#700');
|
|
160
|
+
});
|
|
161
|
+
it('flags a NEGATED close keyword (presence invariant, no negation parser)', () => {
|
|
162
|
+
const e = evaluatePrMerge({ title: 'feat: x', body: 'Does not close #2466', repo });
|
|
163
|
+
expect(e.ok).toBe(false);
|
|
164
|
+
expect(e.undeclared).toContain('#2466');
|
|
165
|
+
});
|
|
166
|
+
it('flags an EMPHASIZED close keyword', () => {
|
|
167
|
+
const e = evaluatePrMerge({ title: 'feat: x', body: '**Fixes #700**', repo });
|
|
168
|
+
expect(e.ok).toBe(false);
|
|
169
|
+
});
|
|
170
|
+
it('flags a QUOTED close keyword', () => {
|
|
171
|
+
const e = evaluatePrMerge({ title: 'feat: x', body: '> closes #12', repo });
|
|
172
|
+
expect(e.ok).toBe(false);
|
|
173
|
+
});
|
|
174
|
+
it('flags a QUALIFIED close keyword ref', () => {
|
|
175
|
+
const e = evaluatePrMerge({ title: 'feat: x', body: 'resolves mmnto-ai/totem#2466', repo });
|
|
176
|
+
expect(e.ok).toBe(false);
|
|
177
|
+
expect(e.undeclared).toContain('mmnto-ai/totem#2466');
|
|
178
|
+
});
|
|
179
|
+
it('flags MULTIPLE refs', () => {
|
|
180
|
+
const e = evaluatePrMerge({ title: 'feat: x', body: 'Fixes: #55 and Resolved #56', repo });
|
|
181
|
+
expect(e.ok).toBe(false);
|
|
182
|
+
expect(e.undeclared).toEqual(expect.arrayContaining(['#55', '#56']));
|
|
183
|
+
});
|
|
184
|
+
it('catches a TITLE-only close keyword', () => {
|
|
185
|
+
const e = evaluatePrMerge({ title: 'Fixes #55', body: 'clean body', repo });
|
|
186
|
+
expect(e.ok).toBe(false);
|
|
187
|
+
expect(e.undeclared).toContain('#55');
|
|
188
|
+
});
|
|
189
|
+
it('AUTHORIZES a close keyword declared by a totem-close marker (marker never self-flags)', () => {
|
|
190
|
+
const e = evaluatePrMerge({
|
|
191
|
+
title: 'feat: x',
|
|
192
|
+
body: '<!-- totem-close: #55 -->\nFixes #55',
|
|
193
|
+
repo,
|
|
194
|
+
});
|
|
195
|
+
expect(e.ok).toBe(true);
|
|
196
|
+
expect(e.declaredByMarker).toContain('#55');
|
|
197
|
+
expect(e.undeclared).toEqual([]);
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
describe('prMergeCommand — happy path', () => {
|
|
201
|
+
it('merges a clean PR squash-only', async () => {
|
|
202
|
+
const h = makeHarness();
|
|
203
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: false, closeDeclared: false }, h.deps);
|
|
204
|
+
expect(exitCode).toBe(0);
|
|
205
|
+
expect(h.mergeCalled()).toBe(true);
|
|
206
|
+
const merge = h.calls.find((a) => a[0] === 'pr' && a[1] === 'merge');
|
|
207
|
+
expect(merge).toEqual([
|
|
208
|
+
'pr',
|
|
209
|
+
'merge',
|
|
210
|
+
'5',
|
|
211
|
+
'--repo',
|
|
212
|
+
'mmnto-ai/totem',
|
|
213
|
+
'--squash',
|
|
214
|
+
'--match-head-commit',
|
|
215
|
+
'deadbeef',
|
|
216
|
+
]);
|
|
217
|
+
});
|
|
218
|
+
it('forwards an explicit PR number to `gh pr view`', async () => {
|
|
219
|
+
const h = makeHarness({
|
|
220
|
+
pr: { title: 't', body: 'clean', state: 'OPEN', number: 88, headRefOid: 'x' },
|
|
221
|
+
});
|
|
222
|
+
await prMergeCommand('88', { checkOnly: false, closeDeclared: false }, h.deps);
|
|
223
|
+
const view = h.calls.find((a) => a[0] === 'pr' && a[1] === 'view');
|
|
224
|
+
expect(view).toContain('88');
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
describe('prMergeCommand — refuses (abortsMergeOnFailedAutocloseEvaluation)', () => {
|
|
228
|
+
it('exits 1 and NEVER merges when an undeclared close-keyword ref is present', async () => {
|
|
229
|
+
const h = makeHarness({
|
|
230
|
+
pr: { title: 'feat: x', body: 'Fixes #700', state: 'OPEN', number: 5, headRefOid: 'x' },
|
|
231
|
+
});
|
|
232
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: false, closeDeclared: false }, h.deps);
|
|
233
|
+
expect(exitCode).toBe(1);
|
|
234
|
+
expect(h.mergeCalled()).toBe(false);
|
|
235
|
+
expect(h.err()).toContain('#700');
|
|
236
|
+
expect(h.err()).toContain('totem-close');
|
|
237
|
+
});
|
|
238
|
+
it('exits 1 on a NEGATED close keyword (still blocks) and never merges', async () => {
|
|
239
|
+
const h = makeHarness({
|
|
240
|
+
pr: {
|
|
241
|
+
title: 'feat: x',
|
|
242
|
+
body: 'Does not close #2466',
|
|
243
|
+
state: 'OPEN',
|
|
244
|
+
number: 5,
|
|
245
|
+
headRefOid: 'x',
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: false, closeDeclared: false }, h.deps);
|
|
249
|
+
expect(exitCode).toBe(1);
|
|
250
|
+
expect(h.mergeCalled()).toBe(false);
|
|
251
|
+
});
|
|
252
|
+
it('exits 1 on a TITLE-only close keyword', async () => {
|
|
253
|
+
const h = makeHarness({
|
|
254
|
+
pr: { title: 'Fixes #55', body: 'clean', state: 'OPEN', number: 5, headRefOid: 'x' },
|
|
255
|
+
});
|
|
256
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: false, closeDeclared: false }, h.deps);
|
|
257
|
+
expect(exitCode).toBe(1);
|
|
258
|
+
expect(h.mergeCalled()).toBe(false);
|
|
259
|
+
});
|
|
260
|
+
it('merges when the close keyword IS marker-authorized', async () => {
|
|
261
|
+
const h = makeHarness({
|
|
262
|
+
pr: {
|
|
263
|
+
title: 'feat: x',
|
|
264
|
+
body: '<!-- totem-close: #55 -->\nFixes #55',
|
|
265
|
+
state: 'OPEN',
|
|
266
|
+
number: 5,
|
|
267
|
+
headRefOid: 'x',
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: false, closeDeclared: false }, h.deps);
|
|
271
|
+
expect(exitCode).toBe(0);
|
|
272
|
+
expect(h.mergeCalled()).toBe(true);
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
describe('prMergeCommand — posture + fail-closed', () => {
|
|
276
|
+
it('exits 1 on merge-config drift, names the field, never merges', async () => {
|
|
277
|
+
const h = makeHarness({
|
|
278
|
+
posture: { ...CONFORMING_POSTURE, squashMergeCommitMessage: 'COMMIT_MESSAGES' },
|
|
279
|
+
});
|
|
280
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: false, closeDeclared: false }, h.deps);
|
|
281
|
+
expect(exitCode).toBe(1);
|
|
282
|
+
expect(h.mergeCalled()).toBe(false);
|
|
283
|
+
expect(h.err()).toContain('squash_merge_commit_message');
|
|
284
|
+
});
|
|
285
|
+
it('exits 1 on squash-only drift (merge-commit still enabled)', async () => {
|
|
286
|
+
const h = makeHarness({ posture: { ...CONFORMING_POSTURE, mergeCommitAllowed: true } });
|
|
287
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: false, closeDeclared: false }, h.deps);
|
|
288
|
+
expect(exitCode).toBe(1);
|
|
289
|
+
expect(h.mergeCalled()).toBe(false);
|
|
290
|
+
expect(h.err()).toContain('allow_merge_commit');
|
|
291
|
+
});
|
|
292
|
+
it('fails closed (exit 1, no merge) when `gh repo view` throws', async () => {
|
|
293
|
+
const h = makeHarness({
|
|
294
|
+
throwOn: (a) => (a[0] === 'repo' ? new Error('gh: not authenticated') : undefined),
|
|
295
|
+
});
|
|
296
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: false, closeDeclared: false }, h.deps);
|
|
297
|
+
expect(exitCode).toBe(1);
|
|
298
|
+
expect(h.mergeCalled()).toBe(false);
|
|
299
|
+
expect(h.err()).toContain('failing closed');
|
|
300
|
+
});
|
|
301
|
+
it('fails closed when `gh pr view` throws', async () => {
|
|
302
|
+
const h = makeHarness({
|
|
303
|
+
throwOn: (a) => a[0] === 'pr' && a[1] === 'view' ? new Error('no PR for branch') : undefined,
|
|
304
|
+
});
|
|
305
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: false, closeDeclared: false }, h.deps);
|
|
306
|
+
expect(exitCode).toBe(1);
|
|
307
|
+
expect(h.mergeCalled()).toBe(false);
|
|
308
|
+
});
|
|
309
|
+
it('fails closed on a non-OPEN PR', async () => {
|
|
310
|
+
const h = makeHarness({
|
|
311
|
+
pr: { title: 't', body: 'clean', state: 'MERGED', number: 5, headRefOid: 'x' },
|
|
312
|
+
});
|
|
313
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: false, closeDeclared: false }, h.deps);
|
|
314
|
+
expect(exitCode).toBe(1);
|
|
315
|
+
expect(h.mergeCalled()).toBe(false);
|
|
316
|
+
expect(h.err()).toContain('MERGED');
|
|
317
|
+
});
|
|
318
|
+
it('exit 1 propagates when `gh pr merge` itself fails (gh stderr surfaced)', async () => {
|
|
319
|
+
const h = makeHarness({
|
|
320
|
+
throwOn: (a) => (a[0] === 'pr' && a[1] === 'merge' ? new Error('merge conflict') : undefined),
|
|
321
|
+
});
|
|
322
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: false, closeDeclared: false }, h.deps);
|
|
323
|
+
expect(exitCode).toBe(1);
|
|
324
|
+
expect(h.err()).toContain('merge conflict');
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
describe('prMergeCommand — --check-only', () => {
|
|
328
|
+
it('exits 0 on a clean PR WITHOUT merging', async () => {
|
|
329
|
+
const h = makeHarness();
|
|
330
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: true, closeDeclared: false }, h.deps);
|
|
331
|
+
expect(exitCode).toBe(0);
|
|
332
|
+
expect(h.mergeCalled()).toBe(false);
|
|
333
|
+
});
|
|
334
|
+
it('exits 1 on an undeclared ref WITHOUT merging', async () => {
|
|
335
|
+
const h = makeHarness({
|
|
336
|
+
pr: { title: 'feat', body: 'Fixes #700', state: 'OPEN', number: 5, headRefOid: 'x' },
|
|
337
|
+
});
|
|
338
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: true, closeDeclared: false }, h.deps);
|
|
339
|
+
expect(exitCode).toBe(1);
|
|
340
|
+
expect(h.mergeCalled()).toBe(false);
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
describe('prMergeCommand — --close-declared', () => {
|
|
344
|
+
const declaredPr = {
|
|
345
|
+
title: 'feat: x',
|
|
346
|
+
body: '<!-- totem-close: #55, mmnto-ai/totem-strategy#7 -->\nFixes #55',
|
|
347
|
+
state: 'OPEN',
|
|
348
|
+
number: 5,
|
|
349
|
+
headRefOid: 'x',
|
|
350
|
+
};
|
|
351
|
+
it('closes each marker-declared target after merge when opted in', async () => {
|
|
352
|
+
const h = makeHarness({ pr: declaredPr });
|
|
353
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: false, closeDeclared: true }, h.deps);
|
|
354
|
+
expect(exitCode).toBe(0);
|
|
355
|
+
expect(h.mergeCalled()).toBe(true);
|
|
356
|
+
const closes = h.issueCloseCalls();
|
|
357
|
+
expect(closes.some((a) => a.includes('55'))).toBe(true);
|
|
358
|
+
expect(closes.some((a) => a.includes('7') && a.includes('--repo'))).toBe(true);
|
|
359
|
+
});
|
|
360
|
+
it('prints the exact commands and does NOT close by default', async () => {
|
|
361
|
+
const h = makeHarness({ pr: declaredPr });
|
|
362
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: false, closeDeclared: false }, h.deps);
|
|
363
|
+
expect(exitCode).toBe(0);
|
|
364
|
+
expect(h.mergeCalled()).toBe(true);
|
|
365
|
+
expect(h.issueCloseCalls()).toHaveLength(0);
|
|
366
|
+
expect(h.out()).toContain('gh issue close');
|
|
367
|
+
// The printed commands are paste-safe (codex NB-1): quoted comment, no backticks.
|
|
368
|
+
expect(h.out()).not.toContain('`');
|
|
369
|
+
expect(h.out()).toMatch(/gh issue close 55 --repo mmnto-ai\/totem --comment '/);
|
|
370
|
+
});
|
|
371
|
+
it('exit 1 + summary when a requested close fails; still attempts every target (codex B-4)', async () => {
|
|
372
|
+
const h = makeHarness({
|
|
373
|
+
pr: declaredPr,
|
|
374
|
+
throwOn: (a) => a[0] === 'issue' && a[1] === 'close' && a.includes('55')
|
|
375
|
+
? new Error('denied: not a collaborator')
|
|
376
|
+
: undefined,
|
|
377
|
+
});
|
|
378
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: false, closeDeclared: true }, h.deps);
|
|
379
|
+
expect(exitCode).toBe(1);
|
|
380
|
+
expect(h.mergeCalled()).toBe(true);
|
|
381
|
+
// Continued through ALL targets despite the #55 failure.
|
|
382
|
+
const closes = h.issueCloseCalls();
|
|
383
|
+
expect(closes.some((a) => a.includes('55'))).toBe(true);
|
|
384
|
+
expect(closes.some((a) => a.includes('7'))).toBe(true);
|
|
385
|
+
// The final summary names the failed target.
|
|
386
|
+
expect(h.err()).toMatch(/FAILED.*#55/);
|
|
387
|
+
});
|
|
388
|
+
});
|
|
389
|
+
describe('prMergeCommand — confused-deputy positional (codex B-2)', () => {
|
|
390
|
+
it('refuses a URL positional BEFORE any gh call (throws, never merges)', async () => {
|
|
391
|
+
const h = makeHarness();
|
|
392
|
+
await expect(prMergeCommand('https://github.com/other/repo/pull/5', { checkOnly: false, closeDeclared: false }, h.deps)).rejects.toThrow(/invalid PR argument/i);
|
|
393
|
+
expect(h.calls).toHaveLength(0);
|
|
394
|
+
expect(h.mergeCalled()).toBe(false);
|
|
395
|
+
});
|
|
396
|
+
it('binds --repo on BOTH `gh pr view` and `gh pr merge` to the resolved repo', async () => {
|
|
397
|
+
const h = makeHarness({
|
|
398
|
+
pr: { title: 't', body: 'clean', state: 'OPEN', number: 88, headRefOid: 'oid88' },
|
|
399
|
+
});
|
|
400
|
+
await prMergeCommand('88', { checkOnly: false, closeDeclared: false }, h.deps);
|
|
401
|
+
const view = h.calls.find((a) => a[0] === 'pr' && a[1] === 'view' && a.includes('88'));
|
|
402
|
+
const merge = h.calls.find((a) => a[0] === 'pr' && a[1] === 'merge');
|
|
403
|
+
expect(view?.[view.indexOf('--repo') + 1]).toBe('mmnto-ai/totem');
|
|
404
|
+
expect(merge?.[merge.indexOf('--repo') + 1]).toBe('mmnto-ai/totem');
|
|
405
|
+
// Snapshot binding uses the fetched head oid.
|
|
406
|
+
expect(merge?.[merge.indexOf('--match-head-commit') + 1]).toBe('oid88');
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
describe('prMergeCommand — landing-state read failure (codex round-2 BLOCKING)', () => {
|
|
410
|
+
const declaredPr = {
|
|
411
|
+
title: 'feat: x',
|
|
412
|
+
body: '<!-- totem-close: #55 -->\nFixes #55',
|
|
413
|
+
state: 'OPEN',
|
|
414
|
+
number: 5,
|
|
415
|
+
headRefOid: 'x',
|
|
416
|
+
};
|
|
417
|
+
const throwOnStateRead = (a) => a[0] === 'pr' && a[1] === 'view' && a.includes('state,mergedAt')
|
|
418
|
+
? new Error('network unreachable')
|
|
419
|
+
: undefined;
|
|
420
|
+
it('with --close-declared: UNCONFIRMED (never "merged"), exit 1, names deferred targets, closes none', async () => {
|
|
421
|
+
const h = makeHarness({ pr: declaredPr, throwOn: throwOnStateRead });
|
|
422
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: false, closeDeclared: true }, h.deps);
|
|
423
|
+
// The merge command ran (irreversible) but its landing is unconfirmed.
|
|
424
|
+
expect(h.mergeCalled()).toBe(true);
|
|
425
|
+
// Partial failure — NOT a false all-actions-success signal (codex round-2).
|
|
426
|
+
expect(exitCode).toBe(1);
|
|
427
|
+
expect(h.issueCloseCalls()).toHaveLength(0);
|
|
428
|
+
expect(h.err()).toMatch(/UNCONFIRMED/);
|
|
429
|
+
expect(h.err()).toMatch(/#55/);
|
|
430
|
+
// NEVER the completed-merge line.
|
|
431
|
+
expect(h.out()).not.toContain('merged PR #5 (--squash)');
|
|
432
|
+
// Finding 4 (codex #4 NB): the recovery text must NOT tell the operator to re-run
|
|
433
|
+
// `totem pr merge` with --close-declared — the pre-merge guard rejects an
|
|
434
|
+
// already-MERGED PR (state !== OPEN) before the close phase, so that re-run is
|
|
435
|
+
// impossible. It must give the valid manual `gh issue close` command(s) instead.
|
|
436
|
+
expect(h.err()).not.toMatch(/re-run `totem pr merge`.*--close-declared/i);
|
|
437
|
+
expect(h.err()).toMatch(/gh issue close 55/);
|
|
438
|
+
});
|
|
439
|
+
it('without --close-declared: still says UNCONFIRMED (not "merged"), exit 0, prints manual close commands', async () => {
|
|
440
|
+
const h = makeHarness({ pr: declaredPr, throwOn: throwOnStateRead });
|
|
441
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: false, closeDeclared: false }, h.deps);
|
|
442
|
+
expect(exitCode).toBe(0);
|
|
443
|
+
expect(h.err()).toMatch(/UNCONFIRMED/);
|
|
444
|
+
expect(h.out()).not.toContain('merged PR #5 (--squash)');
|
|
445
|
+
expect(h.issueCloseCalls()).toHaveLength(0);
|
|
446
|
+
// Manual-close-guidance parity (CR B-only round): the declared command is still
|
|
447
|
+
// surfaced without --close-declared, and never as a --close-declared re-run.
|
|
448
|
+
expect(h.err()).toMatch(/gh issue close 55/);
|
|
449
|
+
expect(h.err()).not.toMatch(/re-run `totem pr merge`.*--close-declared/i);
|
|
450
|
+
});
|
|
451
|
+
});
|
|
452
|
+
describe('prMergeCommand — snapshot binding / head mismatch (codex Q)', () => {
|
|
453
|
+
it('exit 1 + re-evaluate instruction when the head-bound merge fails', async () => {
|
|
454
|
+
const h = makeHarness({
|
|
455
|
+
throwOn: (a) => a[0] === 'pr' && a[1] === 'merge'
|
|
456
|
+
? new Error('Pull request is not mergeable: head branch was modified')
|
|
457
|
+
: undefined,
|
|
458
|
+
});
|
|
459
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: false, closeDeclared: false }, h.deps);
|
|
460
|
+
expect(exitCode).toBe(1);
|
|
461
|
+
expect(h.err()).toMatch(/re-run `totem pr merge` to re-evaluate/i);
|
|
462
|
+
// No closes attempted after a failed merge.
|
|
463
|
+
expect(h.issueCloseCalls()).toHaveLength(0);
|
|
464
|
+
});
|
|
465
|
+
});
|
|
466
|
+
describe('prMergeCommand — merge-queue semantics (codex B-5)', () => {
|
|
467
|
+
const queuedDeclaredPr = {
|
|
468
|
+
title: 'feat: x',
|
|
469
|
+
body: '<!-- totem-close: #55 -->\nFixes #55',
|
|
470
|
+
state: 'OPEN',
|
|
471
|
+
number: 5,
|
|
472
|
+
headRefOid: 'x',
|
|
473
|
+
};
|
|
474
|
+
it('a non-MERGED landing state DEFERS closes and exits 0', async () => {
|
|
475
|
+
const h = makeHarness({ pr: queuedDeclaredPr, mergedState: 'OPEN' });
|
|
476
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: false, closeDeclared: true }, h.deps);
|
|
477
|
+
expect(exitCode).toBe(0);
|
|
478
|
+
expect(h.mergeCalled()).toBe(true);
|
|
479
|
+
// The merge was invoked, but no issue was closed (deferred).
|
|
480
|
+
expect(h.issueCloseCalls()).toHaveLength(0);
|
|
481
|
+
expect(h.out()).toMatch(/not yet MERGED|merge queue|auto-merge/i);
|
|
482
|
+
expect(h.out()).toMatch(/DEFERRED/);
|
|
483
|
+
// Does NOT print the completed-merge line.
|
|
484
|
+
expect(h.out()).not.toContain('merged PR #5 (--squash)');
|
|
485
|
+
});
|
|
486
|
+
it('a MERGED landing state proceeds to the merged message + closes', async () => {
|
|
487
|
+
const h = makeHarness({ pr: queuedDeclaredPr, mergedState: 'MERGED' });
|
|
488
|
+
const { exitCode } = await prMergeCommand(undefined, { checkOnly: false, closeDeclared: true }, h.deps);
|
|
489
|
+
expect(exitCode).toBe(0);
|
|
490
|
+
expect(h.out()).toContain('merged PR #5 (--squash)');
|
|
491
|
+
expect(h.issueCloseCalls().some((a) => a.includes('55'))).toBe(true);
|
|
492
|
+
});
|
|
493
|
+
});
|
|
494
|
+
//# sourceMappingURL=pr.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr.test.js","sourceRoot":"","sources":["../../src/commands/pr.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -410,6 +410,40 @@ program
|
|
|
410
410
|
handleError(err);
|
|
411
411
|
}
|
|
412
412
|
});
|
|
413
|
+
// ─── `totem pr merge` — auto-close-safe squash merge actuator (mmnto-ai/totem#1762) ───
|
|
414
|
+
// The sanctioned paved-road merge path (no command interception — OPTION 1
|
|
415
|
+
// ruling, 2026-07-22). Custom fail-closed exit-code contract (the index
|
|
416
|
+
// wrapper sets process.exitCode; the command never process.exit's mid-flow, same
|
|
417
|
+
// as `mail`): 0 = merged / clean --check-only; 1 = posture drift, an undeclared
|
|
418
|
+
// close-keyword ref, or ANY gh/env failure (NO merge attempted).
|
|
419
|
+
const prCmd = program
|
|
420
|
+
.command('pr')
|
|
421
|
+
.description('Pull-request actuators (auto-close-safe merge — mmnto-ai/totem#1762)');
|
|
422
|
+
prCmd
|
|
423
|
+
.command('merge [number]')
|
|
424
|
+
.description('Merge a PR squash-only after asserting merge-config posture + auto-close safety (no body flags, ever)')
|
|
425
|
+
.option('--check-only', 'Evaluate posture + auto-close safety and exit 0/1 WITHOUT merging')
|
|
426
|
+
.option('--close-declared', 'After a successful merge, close each totem-close-marker-declared issue (default: print the commands instead)')
|
|
427
|
+
.action(async (number, opts) => {
|
|
428
|
+
requireGhCli();
|
|
429
|
+
try {
|
|
430
|
+
const { assertValidPrNumberArg, prMergeCommand } = await import('./commands/pr.js');
|
|
431
|
+
// Validate at the Commander boundary too (defense in depth, codex B-2): a
|
|
432
|
+
// URL/branch positional is refused before any gh call.
|
|
433
|
+
assertValidPrNumberArg(number);
|
|
434
|
+
const { exitCode } = await prMergeCommand(number, {
|
|
435
|
+
checkOnly: opts.checkOnly === true,
|
|
436
|
+
closeDeclared: opts.closeDeclared === true,
|
|
437
|
+
});
|
|
438
|
+
if (exitCode !== 0)
|
|
439
|
+
process.exitCode = exitCode;
|
|
440
|
+
}
|
|
441
|
+
catch (err) {
|
|
442
|
+
handleError(err);
|
|
443
|
+
// totem-context: handleError returns `never` (process.exit), so the throw is unreachable but required to satisfy the Tenet 4 fail-loud rule that bans bare-catch silent-degrade. Mirrors the mail/orient pattern.
|
|
444
|
+
throw err;
|
|
445
|
+
}
|
|
446
|
+
});
|
|
413
447
|
program
|
|
414
448
|
.command('retrospect <pr-number>')
|
|
415
449
|
.description('Bot-tax circuit-breaker — push-grouped review-round retrospective with route-out heuristics (mmnto-ai/totem#1713)')
|