@mmnto/cli 2.2.1 → 2.4.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/config-drift.test.js +4 -1
- package/dist/commands/config-drift.test.js.map +1 -1
- package/dist/commands/gate-install.d.ts +17 -0
- package/dist/commands/gate-install.d.ts.map +1 -1
- package/dist/commands/gate-install.js +23 -0
- package/dist/commands/gate-install.js.map +1 -1
- package/dist/commands/gate-install.test.js +467 -0
- package/dist/commands/gate-install.test.js.map +1 -1
- package/dist/commands/gate.d.ts +9 -0
- package/dist/commands/gate.d.ts.map +1 -1
- package/dist/commands/gate.js +24 -2
- package/dist/commands/gate.js.map +1 -1
- package/dist/commands/gate.test.js +42 -1
- package/dist/commands/gate.test.js.map +1 -1
- package/dist/commands/init-templates.d.ts +5 -5
- package/dist/commands/init-templates.d.ts.map +1 -1
- package/dist/commands/init-templates.js +758 -79
- package/dist/commands/init-templates.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +8 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/init.test.js +122 -0
- package/dist/commands/init.test.js.map +1 -1
- package/dist/commands/mail-cli-wiring.test.js +58 -2
- package/dist/commands/mail-cli-wiring.test.js.map +1 -1
- package/dist/commands/mail-derive-seat.test.d.ts +28 -0
- package/dist/commands/mail-derive-seat.test.d.ts.map +1 -0
- package/dist/commands/mail-derive-seat.test.js +557 -0
- package/dist/commands/mail-derive-seat.test.js.map +1 -0
- package/dist/commands/mail.d.ts +112 -0
- package/dist/commands/mail.d.ts.map +1 -1
- package/dist/commands/mail.js +189 -0
- package/dist/commands/mail.js.map +1 -1
- package/dist/commands/resolve-threads-cli-wiring.test.d.ts +19 -0
- package/dist/commands/resolve-threads-cli-wiring.test.d.ts.map +1 -0
- package/dist/commands/resolve-threads-cli-wiring.test.js +103 -0
- package/dist/commands/resolve-threads-cli-wiring.test.js.map +1 -0
- package/dist/commands/resolve-threads.d.ts +472 -0
- package/dist/commands/resolve-threads.d.ts.map +1 -0
- package/dist/commands/resolve-threads.js +793 -0
- package/dist/commands/resolve-threads.js.map +1 -0
- package/dist/commands/resolve-threads.test.d.ts +2 -0
- package/dist/commands/resolve-threads.test.d.ts.map +1 -0
- package/dist/commands/resolve-threads.test.js +1123 -0
- package/dist/commands/resolve-threads.test.js.map +1 -0
- package/dist/commands/sync-labels-forms.test.d.ts +7 -4
- package/dist/commands/sync-labels-forms.test.d.ts.map +1 -1
- package/dist/commands/sync-labels-forms.test.js +266 -18
- package/dist/commands/sync-labels-forms.test.js.map +1 -1
- package/dist/index.js +74 -5
- package/dist/index.js.map +1 -1
- package/dist/parsers/bot-identity-parity.test.d.ts +2 -0
- package/dist/parsers/bot-identity-parity.test.d.ts.map +1 -0
- package/dist/parsers/bot-identity-parity.test.js +229 -0
- package/dist/parsers/bot-identity-parity.test.js.map +1 -0
- package/dist/parsers/bot-review-parser.d.ts +8 -5
- package/dist/parsers/bot-review-parser.d.ts.map +1 -1
- package/dist/parsers/bot-review-parser.js +12 -34
- package/dist/parsers/bot-review-parser.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command-surface (Commander parser) tests for the `totem resolve-threads`
|
|
3
|
+
* wiring (mmnto-ai/totem#2841).
|
|
4
|
+
*
|
|
5
|
+
* `index.ts` builds its `program` at module scope and auto-runs `parseAsync` on
|
|
6
|
+
* import, so it cannot be imported without executing the CLI against the test
|
|
7
|
+
* runner's argv. This therefore tests a hand-maintained MIRROR of the
|
|
8
|
+
* registration (`buildProgram` below), not `index.ts` itself — the same
|
|
9
|
+
* structural limit `mail-cli-wiring.test.ts` and `seat-cli-wiring.test.ts`
|
|
10
|
+
* document.
|
|
11
|
+
*
|
|
12
|
+
* The lock that earns this file: the program-level `--json` SWALLOWS a
|
|
13
|
+
* post-subcommand `--json` (the mmnto-ai/totem#2097 parent/child option
|
|
14
|
+
* collision). A built-binary run of `totem resolve-threads 2839 --json` printed
|
|
15
|
+
* the human rows and no JSON before the action was switched to
|
|
16
|
+
* `optsWithGlobals()`. Parser-level only: no gh, no network, no core import.
|
|
17
|
+
*/
|
|
18
|
+
import * as fs from 'node:fs';
|
|
19
|
+
import * as path from 'node:path';
|
|
20
|
+
import { Command } from 'commander';
|
|
21
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
22
|
+
/** Mirror of the `resolve-threads` registration in index.ts. */
|
|
23
|
+
function buildProgram(handler) {
|
|
24
|
+
const program = new Command();
|
|
25
|
+
program.exitOverride(); // throw on parse error instead of process.exit
|
|
26
|
+
// The program-level `--json` is what makes the collision reachable.
|
|
27
|
+
program.option('--json', 'Output structured JSON to stdout');
|
|
28
|
+
program
|
|
29
|
+
.command('resolve-threads <pr-number>')
|
|
30
|
+
.option('--apply', 'Run the resolveReviewThread mutation (default: print the plan only)')
|
|
31
|
+
.option('--ids <ids>', 'Comma-separated REST root comment ids to narrow the batch')
|
|
32
|
+
.option('--json', 'Emit the plan rows as one JSON document')
|
|
33
|
+
.action((prNumber, _opts, cmd) => {
|
|
34
|
+
// EXACT read from index.ts.
|
|
35
|
+
const { apply, ids, json } = cmd.optsWithGlobals();
|
|
36
|
+
handler(prNumber, {
|
|
37
|
+
apply: apply === true,
|
|
38
|
+
...(ids === undefined ? {} : { ids }),
|
|
39
|
+
json: json === true,
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
return program;
|
|
43
|
+
}
|
|
44
|
+
describe('resolve-threads CLI command-surface (Commander wiring, mmnto-ai/totem#2841)', () => {
|
|
45
|
+
it('defaults to dry-run: no --apply, no --ids, no --json', () => {
|
|
46
|
+
const handler = vi.fn();
|
|
47
|
+
buildProgram(handler).parse(['node', 'totem', 'resolve-threads', '2839']);
|
|
48
|
+
expect(handler).toHaveBeenCalledTimes(1);
|
|
49
|
+
expect(handler.mock.calls[0][0]).toBe('2839');
|
|
50
|
+
expect(handler.mock.calls[0][1]).toEqual({ apply: false, json: false });
|
|
51
|
+
});
|
|
52
|
+
it('--apply parses to apply: true', () => {
|
|
53
|
+
const handler = vi.fn();
|
|
54
|
+
buildProgram(handler).parse(['node', 'totem', 'resolve-threads', '2839', '--apply']);
|
|
55
|
+
expect(handler.mock.calls[0][1].apply).toBe(true);
|
|
56
|
+
});
|
|
57
|
+
it('--ids carries the comma list through verbatim', () => {
|
|
58
|
+
const handler = vi.fn();
|
|
59
|
+
buildProgram(handler).parse([
|
|
60
|
+
'node',
|
|
61
|
+
'totem',
|
|
62
|
+
'resolve-threads',
|
|
63
|
+
'2839',
|
|
64
|
+
'--ids',
|
|
65
|
+
'3954062164,3954067481',
|
|
66
|
+
]);
|
|
67
|
+
expect(handler.mock.calls[0][1].ids).toBe('3954062164,3954067481');
|
|
68
|
+
});
|
|
69
|
+
it('--json AFTER the subcommand still arrives (the #2097 collision)', () => {
|
|
70
|
+
const handler = vi.fn();
|
|
71
|
+
buildProgram(handler).parse(['node', 'totem', 'resolve-threads', '2839', '--json']);
|
|
72
|
+
expect(handler.mock.calls[0][1].json).toBe(true);
|
|
73
|
+
});
|
|
74
|
+
it('--json BEFORE the subcommand arrives too, so both spellings agree', () => {
|
|
75
|
+
const handler = vi.fn();
|
|
76
|
+
buildProgram(handler).parse(['node', 'totem', '--json', 'resolve-threads', '2839']);
|
|
77
|
+
expect(handler.mock.calls[0][1].json).toBe(true);
|
|
78
|
+
});
|
|
79
|
+
it('requires the PR positional', () => {
|
|
80
|
+
const handler = vi.fn();
|
|
81
|
+
expect(() => buildProgram(handler).parse(['node', 'totem', 'resolve-threads'])).toThrow();
|
|
82
|
+
expect(handler).not.toHaveBeenCalled();
|
|
83
|
+
});
|
|
84
|
+
it("the SHIPPED action carries no action-level gh precondition — the verb probes gh itself so --json fails in contract (PR round 1, greptile P1; the leg's F1 sensor)", () => {
|
|
85
|
+
// The mirror above cannot see this, and the verb's own test calls the
|
|
86
|
+
// command directly, so re-inserting `requireGhCli();` as the action's first
|
|
87
|
+
// statement would restore the exact defect with every other test green.
|
|
88
|
+
// Read the registration SOURCE structurally, the way lesson.test.ts reads
|
|
89
|
+
// its deprecation aliases: the `resolve-threads` action block, from its
|
|
90
|
+
// `.command(` to the next `.command(`, must not call requireGhCli.
|
|
91
|
+
const indexSrc = fs.readFileSync(path.join(process.cwd(), 'src/index.ts'), 'utf-8');
|
|
92
|
+
const start = indexSrc.indexOf(".command('resolve-threads <pr-number>')");
|
|
93
|
+
expect(start, 'the resolve-threads registration is present').toBeGreaterThan(-1);
|
|
94
|
+
const next = indexSrc.indexOf('.command(', start + 1);
|
|
95
|
+
const block = indexSrc.slice(start, next === -1 ? undefined : next);
|
|
96
|
+
expect(block).toContain('resolveThreadsCommand(');
|
|
97
|
+
expect(block).not.toMatch(/requireGhCli\(\)\s*;/);
|
|
98
|
+
// The sibling actions still carry it — the sensor is about THIS verb's
|
|
99
|
+
// contract, not a repo-wide retirement of the precondition.
|
|
100
|
+
expect(indexSrc).toMatch(/requireGhCli\(\);/);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
//# sourceMappingURL=resolve-threads-cli-wiring.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-threads-cli-wiring.test.js","sourceRoot":"","sources":["../../src/commands/resolve-threads-cli-wiring.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `totem resolve-threads <pr>` — resolve the bot review threads a round has
|
|
3
|
+
* already dispositioned (mmnto-ai/totem#2841, rulings R1-R4 in
|
|
4
|
+
* `.totem/specs/2841.md`).
|
|
5
|
+
*
|
|
6
|
+
* WHY IT EXISTS: the merge-ready gate's predicate 2 (mmnto-ai/totem#2800)
|
|
7
|
+
* denies a merge while any unresolved, non-outdated review thread rooted by a
|
|
8
|
+
* known review bot is open. The lawful way past it is to RESOLVE the threads a
|
|
9
|
+
* round has answered — not to silence the predicate. This verb does exactly
|
|
10
|
+
* that, deterministically and with zero LLM calls.
|
|
11
|
+
*
|
|
12
|
+
* THE EVIDENCE RULE (R2 verbatim): "An in-thread human reply OR a human
|
|
13
|
+
* PR-level comment created after the thread's root — either suffices." So:
|
|
14
|
+
* - `in-thread-reply`: a comment after the root whose author is not a bot
|
|
15
|
+
* (the CodeRabbit/Greptile routine); or
|
|
16
|
+
* - `pr-level-disposition`: ANY non-bot PR-level (issue) comment created
|
|
17
|
+
* AFTER the thread's root comment. It is NOT keyed to the round-disposition
|
|
18
|
+
* comment specifically — the rule is any non-bot comment that postdates the
|
|
19
|
+
* root, because a PR-level comment is the only lawful answer to a GCA
|
|
20
|
+
* thread (bot-protocols forbids replying to GCA in-thread) and no
|
|
21
|
+
* deterministic reading distinguishes a disposition from other human prose.
|
|
22
|
+
* CONSEQUENCE, stated because it is load-bearing: on a re-invoked round the
|
|
23
|
+
* operator's trigger comment ("@coderabbitai review") is itself non-bot
|
|
24
|
+
* evidence for every thread it postdates — which is exactly why the round
|
|
25
|
+
* disposition must be posted BEFORE this verb runs (the review-reply
|
|
26
|
+
* skill's step 4 ordering), not after.
|
|
27
|
+
* A thread with neither is a `skip:no-evidence` row and is NEVER resolved,
|
|
28
|
+
* under any flag. There is no override.
|
|
29
|
+
*
|
|
30
|
+
* WHAT COUNTS AS A BOT, on each surface (the fail-open trap this holds shut):
|
|
31
|
+
* the four review-bot logins are core's closed list, but ANY GitHub App can
|
|
32
|
+
* comment — `github-actions[bot]`, a Copilot reviewer, a scanner — and an App's
|
|
33
|
+
* comment is not a human answer. So a comment is a bot's when GraphQL says
|
|
34
|
+
* `author.__typename === 'Bot'`, or the login ends in `[bot]`, or it is on
|
|
35
|
+
* core's exact list; on REST, when `user.type === 'Bot'`, or the login ends in
|
|
36
|
+
* `[bot]`, or core's loose review-bot pattern matches. Only what survives all
|
|
37
|
+
* three arms is evidence. A DELETED account (null author) is deliberately NOT a
|
|
38
|
+
* bot: the reply it left was a human reply when it was written, and deleting
|
|
39
|
+
* the account does not retract it (recorded as item (6) of the design's
|
|
40
|
+
* disagreement list in `.totem/specs/2841.md`).
|
|
41
|
+
*
|
|
42
|
+
* SAFETY PROPERTIES this module holds:
|
|
43
|
+
* - Dry-run by DEFAULT. `--apply` is the only path that mutates.
|
|
44
|
+
* - The verb NEVER posts a comment, a reply or a review. The only mutation it
|
|
45
|
+
* can issue is `resolveReviewThread`.
|
|
46
|
+
* - A read that could not be completed (a `hasNextPage` it cannot follow, a
|
|
47
|
+
* page budget blown, a `gh` failure, a GraphQL `errors` body) is a HARD
|
|
48
|
+
* failure — exit 1, nothing resolved. Never a shorter list silently
|
|
49
|
+
* treated as the whole PR (the no-silent-shrink rule the spine reader and
|
|
50
|
+
* merge-ready both hold).
|
|
51
|
+
* - A human-rooted thread is never a candidate, whatever its state.
|
|
52
|
+
* - Every bot-rooted thread prints exactly one row carrying its REST root
|
|
53
|
+
* comment id (R4), so nothing is skipped silently.
|
|
54
|
+
*
|
|
55
|
+
* Every `gh` call goes through the injected {@link GhRunner} seam (the
|
|
56
|
+
* mmnto-ai/totem#2800 shape: argv in, `{ stdout, exitCode }` out — never a
|
|
57
|
+
* shell string), so the tests run fully offline against checked-in captures.
|
|
58
|
+
*/
|
|
59
|
+
import { z } from 'zod';
|
|
60
|
+
import type { GhRunner } from '@mmnto/totem';
|
|
61
|
+
/**
|
|
62
|
+
* The thread read. `comments(first:)` carries `databaseId` — the REST comment
|
|
63
|
+
* id `totem triage-pr` prints as a finding's `rootCommentId`, which is what
|
|
64
|
+
* `--ids` selects on and what every row prints (R4).
|
|
65
|
+
*/
|
|
66
|
+
export declare const RESOLVE_THREADS_QUERY = "query TotemResolveThreads($owner: String!, $name: String!, $number: Int!, $threadsAfter: String) {\n repository(owner: $owner, name: $name) {\n pullRequest(number: $number) {\n reviewThreads(first: 100, after: $threadsAfter) {\n pageInfo { hasNextPage endCursor }\n nodes {\n id\n isResolved\n isOutdated\n path\n comments(first: 100) {\n pageInfo { hasNextPage endCursor }\n nodes {\n databaseId\n author { __typename login }\n createdAt\n }\n }\n }\n }\n }\n }\n}";
|
|
67
|
+
/**
|
|
68
|
+
* The per-thread comment continuation. A nested connection cannot be paged from
|
|
69
|
+
* the outer document (one cursor cannot address many threads), so a thread that
|
|
70
|
+
* reports `comments.pageInfo.hasNextPage` is followed by node id until it is
|
|
71
|
+
* complete. A page that cannot be followed is a failed read, not a short list.
|
|
72
|
+
*/
|
|
73
|
+
export declare const RESOLVE_THREAD_COMMENTS_QUERY = "query TotemResolveThreadComments($threadId: ID!, $commentsAfter: String) {\n node(id: $threadId) {\n ... on PullRequestReviewThread {\n comments(first: 100, after: $commentsAfter) {\n pageInfo { hasNextPage endCursor }\n nodes {\n databaseId\n author { __typename login }\n createdAt\n }\n }\n }\n }\n}";
|
|
74
|
+
/**
|
|
75
|
+
* The ONLY mutation this verb can issue. It asks the thread back with
|
|
76
|
+
* `isResolved` so the run can CONFIRM the outcome rather than infer it from a
|
|
77
|
+
* clean exit (see {@link confirmResolved}).
|
|
78
|
+
*/
|
|
79
|
+
export declare const RESOLVE_THREAD_MUTATION = "mutation TotemResolveReviewThread($threadId: ID!) {\n resolveReviewThread(input: { threadId: $threadId }) {\n thread { id isResolved }\n }\n}";
|
|
80
|
+
/**
|
|
81
|
+
* `author` is null for a deleted/ghost account — never coerced to a bot.
|
|
82
|
+
* `__typename` is REQUIRED, not optional: both documents select it, and it is
|
|
83
|
+
* the only signal that catches a GitHub App outside core's four-name review-bot
|
|
84
|
+
* list (`github-actions`, a Copilot reviewer, a scanner). Making it optional
|
|
85
|
+
* would let a document that quietly stopped selecting it fail OPEN — every App
|
|
86
|
+
* reply reading as a human reply. Absent ⇒ the read fails loud instead.
|
|
87
|
+
*/
|
|
88
|
+
declare const GqlCommentSchema: z.ZodObject<{
|
|
89
|
+
databaseId: z.ZodNullable<z.ZodNumber>;
|
|
90
|
+
author: z.ZodNullable<z.ZodObject<{
|
|
91
|
+
__typename: z.ZodString;
|
|
92
|
+
login: z.ZodString;
|
|
93
|
+
}, "strip", z.ZodTypeAny, {
|
|
94
|
+
login: string;
|
|
95
|
+
__typename: string;
|
|
96
|
+
}, {
|
|
97
|
+
login: string;
|
|
98
|
+
__typename: string;
|
|
99
|
+
}>>;
|
|
100
|
+
createdAt: z.ZodString;
|
|
101
|
+
}, "strip", z.ZodTypeAny, {
|
|
102
|
+
createdAt: string;
|
|
103
|
+
author: {
|
|
104
|
+
login: string;
|
|
105
|
+
__typename: string;
|
|
106
|
+
} | null;
|
|
107
|
+
databaseId: number | null;
|
|
108
|
+
}, {
|
|
109
|
+
createdAt: string;
|
|
110
|
+
author: {
|
|
111
|
+
login: string;
|
|
112
|
+
__typename: string;
|
|
113
|
+
} | null;
|
|
114
|
+
databaseId: number | null;
|
|
115
|
+
}>;
|
|
116
|
+
declare const GqlThreadSchema: z.ZodObject<{
|
|
117
|
+
id: z.ZodString;
|
|
118
|
+
isResolved: z.ZodBoolean;
|
|
119
|
+
isOutdated: z.ZodBoolean;
|
|
120
|
+
path: z.ZodString;
|
|
121
|
+
comments: z.ZodObject<{
|
|
122
|
+
pageInfo: z.ZodObject<{
|
|
123
|
+
hasNextPage: z.ZodBoolean;
|
|
124
|
+
endCursor: z.ZodNullable<z.ZodString>;
|
|
125
|
+
}, "strip", z.ZodTypeAny, {
|
|
126
|
+
hasNextPage: boolean;
|
|
127
|
+
endCursor: string | null;
|
|
128
|
+
}, {
|
|
129
|
+
hasNextPage: boolean;
|
|
130
|
+
endCursor: string | null;
|
|
131
|
+
}>;
|
|
132
|
+
nodes: z.ZodArray<z.ZodObject<{
|
|
133
|
+
databaseId: z.ZodNullable<z.ZodNumber>;
|
|
134
|
+
author: z.ZodNullable<z.ZodObject<{
|
|
135
|
+
__typename: z.ZodString;
|
|
136
|
+
login: z.ZodString;
|
|
137
|
+
}, "strip", z.ZodTypeAny, {
|
|
138
|
+
login: string;
|
|
139
|
+
__typename: string;
|
|
140
|
+
}, {
|
|
141
|
+
login: string;
|
|
142
|
+
__typename: string;
|
|
143
|
+
}>>;
|
|
144
|
+
createdAt: z.ZodString;
|
|
145
|
+
}, "strip", z.ZodTypeAny, {
|
|
146
|
+
createdAt: string;
|
|
147
|
+
author: {
|
|
148
|
+
login: string;
|
|
149
|
+
__typename: string;
|
|
150
|
+
} | null;
|
|
151
|
+
databaseId: number | null;
|
|
152
|
+
}, {
|
|
153
|
+
createdAt: string;
|
|
154
|
+
author: {
|
|
155
|
+
login: string;
|
|
156
|
+
__typename: string;
|
|
157
|
+
} | null;
|
|
158
|
+
databaseId: number | null;
|
|
159
|
+
}>, "many">;
|
|
160
|
+
}, "strip", z.ZodTypeAny, {
|
|
161
|
+
pageInfo: {
|
|
162
|
+
hasNextPage: boolean;
|
|
163
|
+
endCursor: string | null;
|
|
164
|
+
};
|
|
165
|
+
nodes: {
|
|
166
|
+
createdAt: string;
|
|
167
|
+
author: {
|
|
168
|
+
login: string;
|
|
169
|
+
__typename: string;
|
|
170
|
+
} | null;
|
|
171
|
+
databaseId: number | null;
|
|
172
|
+
}[];
|
|
173
|
+
}, {
|
|
174
|
+
pageInfo: {
|
|
175
|
+
hasNextPage: boolean;
|
|
176
|
+
endCursor: string | null;
|
|
177
|
+
};
|
|
178
|
+
nodes: {
|
|
179
|
+
createdAt: string;
|
|
180
|
+
author: {
|
|
181
|
+
login: string;
|
|
182
|
+
__typename: string;
|
|
183
|
+
} | null;
|
|
184
|
+
databaseId: number | null;
|
|
185
|
+
}[];
|
|
186
|
+
}>;
|
|
187
|
+
}, "strip", z.ZodTypeAny, {
|
|
188
|
+
path: string;
|
|
189
|
+
id: string;
|
|
190
|
+
comments: {
|
|
191
|
+
pageInfo: {
|
|
192
|
+
hasNextPage: boolean;
|
|
193
|
+
endCursor: string | null;
|
|
194
|
+
};
|
|
195
|
+
nodes: {
|
|
196
|
+
createdAt: string;
|
|
197
|
+
author: {
|
|
198
|
+
login: string;
|
|
199
|
+
__typename: string;
|
|
200
|
+
} | null;
|
|
201
|
+
databaseId: number | null;
|
|
202
|
+
}[];
|
|
203
|
+
};
|
|
204
|
+
isResolved: boolean;
|
|
205
|
+
isOutdated: boolean;
|
|
206
|
+
}, {
|
|
207
|
+
path: string;
|
|
208
|
+
id: string;
|
|
209
|
+
comments: {
|
|
210
|
+
pageInfo: {
|
|
211
|
+
hasNextPage: boolean;
|
|
212
|
+
endCursor: string | null;
|
|
213
|
+
};
|
|
214
|
+
nodes: {
|
|
215
|
+
createdAt: string;
|
|
216
|
+
author: {
|
|
217
|
+
login: string;
|
|
218
|
+
__typename: string;
|
|
219
|
+
} | null;
|
|
220
|
+
databaseId: number | null;
|
|
221
|
+
}[];
|
|
222
|
+
};
|
|
223
|
+
isResolved: boolean;
|
|
224
|
+
isOutdated: boolean;
|
|
225
|
+
}>;
|
|
226
|
+
/**
|
|
227
|
+
* The REST issue-comment shape. `user.login` keeps its `[bot]` suffix on this
|
|
228
|
+
* surface and `user.type` is `Bot` for every GitHub App — both are read, so an
|
|
229
|
+
* app comment can never pass as the human disposition.
|
|
230
|
+
*/
|
|
231
|
+
declare const RestIssueCommentSchema: z.ZodObject<{
|
|
232
|
+
id: z.ZodNumber;
|
|
233
|
+
user: z.ZodNullable<z.ZodObject<{
|
|
234
|
+
login: z.ZodString;
|
|
235
|
+
type: z.ZodString;
|
|
236
|
+
}, "strip", z.ZodTypeAny, {
|
|
237
|
+
type: string;
|
|
238
|
+
login: string;
|
|
239
|
+
}, {
|
|
240
|
+
type: string;
|
|
241
|
+
login: string;
|
|
242
|
+
}>>;
|
|
243
|
+
created_at: z.ZodOptional<z.ZodString>;
|
|
244
|
+
}, "strip", z.ZodTypeAny, {
|
|
245
|
+
user: {
|
|
246
|
+
type: string;
|
|
247
|
+
login: string;
|
|
248
|
+
} | null;
|
|
249
|
+
id: number;
|
|
250
|
+
created_at?: string | undefined;
|
|
251
|
+
}, {
|
|
252
|
+
user: {
|
|
253
|
+
type: string;
|
|
254
|
+
login: string;
|
|
255
|
+
} | null;
|
|
256
|
+
id: number;
|
|
257
|
+
created_at?: string | undefined;
|
|
258
|
+
}>;
|
|
259
|
+
/** One validated GraphQL review-thread node (the reader's own shape). */
|
|
260
|
+
export type ReviewThreadNode = z.infer<typeof GqlThreadSchema>;
|
|
261
|
+
/** One validated GraphQL review-thread comment node. */
|
|
262
|
+
export type ReviewCommentNode = z.infer<typeof GqlCommentSchema>;
|
|
263
|
+
/** One validated REST issue comment (the PR-level surface). */
|
|
264
|
+
export type RestIssueComment = z.infer<typeof RestIssueCommentSchema>;
|
|
265
|
+
/** One PR review thread, reduced to what the selector reads. */
|
|
266
|
+
export interface ReviewThreadRecord {
|
|
267
|
+
/** The GraphQL node id (`PRRT_…`) the mutation takes. */
|
|
268
|
+
id: string;
|
|
269
|
+
/**
|
|
270
|
+
* `PullRequestReviewComment.databaseId` of the FIRST comment — the REST id
|
|
271
|
+
* `totem triage-pr` carries as a finding's `rootCommentId`. Null only when
|
|
272
|
+
* GitHub answered no id (an `--ids` entry can then never match the row).
|
|
273
|
+
*/
|
|
274
|
+
rootCommentId: number | null;
|
|
275
|
+
/** The root comment's `author.login` (GraphQL spelling, no `[bot]`), or null for a deleted account. */
|
|
276
|
+
rootAuthor: string | null;
|
|
277
|
+
/** The root comment's `createdAt` — the instant PR-level evidence must post AFTER. */
|
|
278
|
+
rootCreatedAt: string;
|
|
279
|
+
isResolved: boolean;
|
|
280
|
+
isOutdated: boolean;
|
|
281
|
+
path: string;
|
|
282
|
+
/** Comments after the root whose author is NOT a known review bot (a null author counts). */
|
|
283
|
+
humanReplyCount: number;
|
|
284
|
+
}
|
|
285
|
+
/** One PR-level (issue) comment, reduced to what the evidence rule reads. */
|
|
286
|
+
export interface PrIssueCommentRecord {
|
|
287
|
+
author: string;
|
|
288
|
+
/** True for a GitHub App (`user.type === 'Bot'`, a `[bot]` login, or a known review bot). */
|
|
289
|
+
isBot: boolean;
|
|
290
|
+
createdAt: string | null;
|
|
291
|
+
}
|
|
292
|
+
/** How the round answered a thread. `none` is never resolvable. */
|
|
293
|
+
export type DispositionEvidence = 'in-thread-reply' | 'pr-level-disposition' | 'none';
|
|
294
|
+
/** What the plan says will happen (or did) to one bot-rooted thread. */
|
|
295
|
+
export type ResolveThreadsVerdict = 'resolve' | 'skip:already-resolved' | 'skip:outdated' | 'skip:no-evidence' | 'skip:not-selected';
|
|
296
|
+
/** One printed row. `--json` carries exactly these fields. */
|
|
297
|
+
export interface ResolveThreadsRow {
|
|
298
|
+
threadId: string;
|
|
299
|
+
rootCommentId: number | null;
|
|
300
|
+
rootAuthor: string | null;
|
|
301
|
+
rootCreatedAt: string;
|
|
302
|
+
path: string;
|
|
303
|
+
isResolved: boolean;
|
|
304
|
+
isOutdated: boolean;
|
|
305
|
+
humanReplyCount: number;
|
|
306
|
+
evidence: DispositionEvidence;
|
|
307
|
+
verdict: ResolveThreadsVerdict;
|
|
308
|
+
/** null under dry-run (nothing was attempted); true/false once `--apply` ran the mutation. */
|
|
309
|
+
applied: boolean | null;
|
|
310
|
+
/** The mutation's failure text when `applied` is false. */
|
|
311
|
+
errorText: string | null;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* The three identity predicates, injected so the pure selector stays free of
|
|
315
|
+
* the heavy core barrel (mmnto-ai/totem#2339) and the tests exercise the
|
|
316
|
+
* SHIPPED classification rather than a copy. All three come from
|
|
317
|
+
* `packages/core/src/bot-identity.ts` (mmnto-ai/totem#2800), the one
|
|
318
|
+
* definition; this file spells no bot name, pattern or suffix of its own, and
|
|
319
|
+
* `bot-identity-parity.test.ts` scans it to keep it that way.
|
|
320
|
+
*/
|
|
321
|
+
export interface BotIdentityPredicates {
|
|
322
|
+
/**
|
|
323
|
+
* The GraphQL surface: `isBotReviewerLoginExact` — a CLOSED-list membership
|
|
324
|
+
* test over a login spelled WITHOUT the `[bot]` suffix. Exact, never a
|
|
325
|
+
* pattern, so no human account can be read as a bot.
|
|
326
|
+
*/
|
|
327
|
+
isBotLoginExact: (login: string) => boolean;
|
|
328
|
+
/** The REST surface: `isBotReviewerLogin` — the loose pattern over a `name[bot]` login. */
|
|
329
|
+
isBotLoginLoose: (login: string) => boolean;
|
|
330
|
+
/** Any surface: `hasBotAppLoginSuffix` — the GitHub App suffix (`name[bot]`) on a login. */
|
|
331
|
+
hasAppSuffix: (login: string) => boolean;
|
|
332
|
+
}
|
|
333
|
+
/** Options for {@link resolveThreadsCommand}. */
|
|
334
|
+
export interface ResolveThreadsOptions {
|
|
335
|
+
/** Run the `resolveReviewThread` mutation. Absent = dry-run (the default). */
|
|
336
|
+
apply?: boolean;
|
|
337
|
+
/** Comma-separated REST root comment ids narrowing the batch (R4). Unmatched entries abort. */
|
|
338
|
+
ids?: string;
|
|
339
|
+
/** Emit one JSON document instead of the human rows. */
|
|
340
|
+
json?: boolean;
|
|
341
|
+
/** Working directory for the default `gh` runner. */
|
|
342
|
+
cwd?: string;
|
|
343
|
+
/** Injectable `gh` seam (tests). Defaults to a `gh`-backed spawn. */
|
|
344
|
+
runner?: GhRunner;
|
|
345
|
+
/** stdout sink (tests). */
|
|
346
|
+
out?: (text: string) => void;
|
|
347
|
+
/** stderr sink (tests). */
|
|
348
|
+
err?: (text: string) => void;
|
|
349
|
+
}
|
|
350
|
+
/** What one run produced. */
|
|
351
|
+
export interface ResolveThreadsResult {
|
|
352
|
+
exitCode: 0 | 1 | 2;
|
|
353
|
+
rows: ResolveThreadsRow[];
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Reduce validated GraphQL threads to {@link ReviewThreadRecord}s. Pure given
|
|
357
|
+
* `identity`. The ENTIRE comment list is inspected — human comments are never
|
|
358
|
+
* filtered out before the classification, because whether a human replied is
|
|
359
|
+
* exactly what the evidence rule reads.
|
|
360
|
+
*/
|
|
361
|
+
export declare function toThreadRecords(threads: readonly ReviewThreadNode[], identity: BotIdentityPredicates): ReviewThreadRecord[];
|
|
362
|
+
/**
|
|
363
|
+
* Is this thread rooted by a review bot? Only bot-rooted threads are candidates
|
|
364
|
+
* (and only they print a row) — a human-rooted thread is never resolved by this
|
|
365
|
+
* verb, whatever its state.
|
|
366
|
+
*/
|
|
367
|
+
export declare function isBotRootedThread(record: ReviewThreadRecord, identity: BotIdentityPredicates): boolean;
|
|
368
|
+
/**
|
|
369
|
+
* Reduce validated REST issue comments to {@link PrIssueCommentRecord}s. Pure
|
|
370
|
+
* given `identity`. The bot test is the REST mirror of {@link isBotComment}'s
|
|
371
|
+
* three arms: GitHub's `user.type === 'Bot'` (every App), a `[bot]`-suffixed
|
|
372
|
+
* login, or core's LOOSE review-bot pattern (the REST surface's own test).
|
|
373
|
+
* A null user (deleted account) is not a bot, for the same reason a null
|
|
374
|
+
* GraphQL author is not.
|
|
375
|
+
*/
|
|
376
|
+
export declare function toPrCommentRecords(comments: readonly RestIssueComment[], identity: BotIdentityPredicates): PrIssueCommentRecord[];
|
|
377
|
+
/**
|
|
378
|
+
* Derive the evidence for one thread (R2). An in-thread human reply wins; else
|
|
379
|
+
* a non-bot PR-level comment created strictly AFTER the thread's root; else
|
|
380
|
+
* `none`. An unparseable instant on either side is not evidence — the
|
|
381
|
+
* conservative direction, since `none` can only ever refuse to resolve.
|
|
382
|
+
*/
|
|
383
|
+
export declare function deriveEvidence(record: ReviewThreadRecord, prComments: readonly PrIssueCommentRecord[]): DispositionEvidence;
|
|
384
|
+
/**
|
|
385
|
+
* The verdict for one candidate thread. PRECEDENCE, most-informative first: an
|
|
386
|
+
* already-resolved or outdated thread reports THAT (it is the fact the operator
|
|
387
|
+
* needs, and neither is ever mutated), then non-selection, then the evidence
|
|
388
|
+
* rule. Only `resolve` ever reaches the mutation.
|
|
389
|
+
*/
|
|
390
|
+
export declare function classifyThread(record: ReviewThreadRecord, evidence: DispositionEvidence, selected: boolean): ResolveThreadsVerdict;
|
|
391
|
+
/** The parsed `--ids` selection, or the error that aborts the run. */
|
|
392
|
+
export type IdSelection = {
|
|
393
|
+
ok: true;
|
|
394
|
+
ids: readonly number[] | null;
|
|
395
|
+
} | {
|
|
396
|
+
ok: false;
|
|
397
|
+
invalid: readonly string[];
|
|
398
|
+
};
|
|
399
|
+
/**
|
|
400
|
+
* Parse `--ids`. `null` (the option absent or empty) means "every evidenced bot
|
|
401
|
+
* thread" — the default (R4). A malformed entry aborts the run exactly like an
|
|
402
|
+
* unmatched one: a typo must never silently narrow the batch.
|
|
403
|
+
*/
|
|
404
|
+
export declare function parseIdSelection(raw: string | undefined): IdSelection;
|
|
405
|
+
/** The plan: one row per bot-rooted thread, plus any selected id that matched nothing. */
|
|
406
|
+
export interface ResolveThreadsPlan {
|
|
407
|
+
rows: ResolveThreadsRow[];
|
|
408
|
+
/** Selected ids matching no bot-rooted thread. Non-empty ⇒ abort before any mutation. */
|
|
409
|
+
unmatchedIds: number[];
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Build the plan. Pure. Every bot-rooted thread yields exactly one row; a
|
|
413
|
+
* human-rooted thread yields none.
|
|
414
|
+
*/
|
|
415
|
+
export declare function buildResolveThreadsPlan(records: readonly ReviewThreadRecord[], prComments: readonly PrIssueCommentRecord[], identity: BotIdentityPredicates, selectedIds: readonly number[] | null): ResolveThreadsPlan;
|
|
416
|
+
/** Build the argv for a `gh api graphql` call. Never a shell string. */
|
|
417
|
+
export declare function graphqlArgs(query: string, variables: ReadonlyArray<readonly [string, string | number]>): string[];
|
|
418
|
+
type ReadFailure = {
|
|
419
|
+
ok: false;
|
|
420
|
+
detail: string;
|
|
421
|
+
};
|
|
422
|
+
type ThreadsRead = {
|
|
423
|
+
ok: true;
|
|
424
|
+
threads: ReviewThreadNode[];
|
|
425
|
+
} | ReadFailure;
|
|
426
|
+
/**
|
|
427
|
+
* Read every review thread on the PR, following BOTH connections' cursors.
|
|
428
|
+
* Any page that cannot be followed — no cursor, the budget blown, a failed or
|
|
429
|
+
* unparseable response — fails the whole read. There is no arm that returns a
|
|
430
|
+
* partial thread set.
|
|
431
|
+
*/
|
|
432
|
+
export declare function readReviewThreads(runner: GhRunner, owner: string, name: string, pr: number): ThreadsRead;
|
|
433
|
+
type PrCommentsRead = {
|
|
434
|
+
ok: true;
|
|
435
|
+
comments: RestIssueComment[];
|
|
436
|
+
} | ReadFailure;
|
|
437
|
+
/**
|
|
438
|
+
* Read the PR's issue comments (REST, `--paginate`). This is the surface where
|
|
439
|
+
* a login keeps its `[bot]` suffix and `user.type` is available, so a bot's own
|
|
440
|
+
* PR-level comment can never be read as the human disposition. A failure here
|
|
441
|
+
* is a HARD failure: evidence cannot be derived, so no thread may be resolved.
|
|
442
|
+
*/
|
|
443
|
+
export declare function readPrIssueComments(runner: GhRunner, owner: string, name: string, pr: number): PrCommentsRead;
|
|
444
|
+
/**
|
|
445
|
+
* Did the mutation actually resolve the thread? `gh` exiting 0 says only that a
|
|
446
|
+
* request was answered; the ANSWER has to say `isResolved: true`. A null
|
|
447
|
+
* payload, a null thread, `isResolved: false`, or a body that does not parse
|
|
448
|
+
* are each a named per-thread failure — a row is never marked applied on a
|
|
449
|
+
* mutation whose result was not read back.
|
|
450
|
+
*/
|
|
451
|
+
export declare function confirmResolved(body: unknown): {
|
|
452
|
+
ok: true;
|
|
453
|
+
} | {
|
|
454
|
+
ok: false;
|
|
455
|
+
detail: string;
|
|
456
|
+
};
|
|
457
|
+
/** One printed row. The REST root comment id is on EVERY row (R4). */
|
|
458
|
+
export declare function formatRow(row: ResolveThreadsRow): string;
|
|
459
|
+
/**
|
|
460
|
+
* Run the verb. Returns the exit code rather than exiting, so `index.ts` owns
|
|
461
|
+
* `process.exitCode` (the `pr merge` / `mail` convention).
|
|
462
|
+
*
|
|
463
|
+
* EXIT CODES:
|
|
464
|
+
* 0 — the plan printed, or `--apply` resolved everything it planned to
|
|
465
|
+
* 1 — a hard read failure (nothing resolved), or `gh` did not answer
|
|
466
|
+
* 2 — an unmatched `--ids` entry (nothing resolved); a mutation that failed;
|
|
467
|
+
* or, under `--apply`, a SELECTED thread skipped for want of evidence
|
|
468
|
+
* (the run did not do what was asked)
|
|
469
|
+
*/
|
|
470
|
+
export declare function resolveThreadsCommand(prArg: string, opts?: ResolveThreadsOptions): Promise<ResolveThreadsResult>;
|
|
471
|
+
export {};
|
|
472
|
+
//# sourceMappingURL=resolve-threads.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-threads.d.ts","sourceRoot":"","sources":["../../src/commands/resolve-threads.ts"],"names":[],"mappings":"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"}
|