@mmnto/cli 1.67.1 → 1.69.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/spine-llm-replay.d.ts +446 -0
- package/dist/commands/spine-llm-replay.d.ts.map +1 -0
- package/dist/commands/spine-llm-replay.js +492 -0
- package/dist/commands/spine-llm-replay.js.map +1 -0
- package/dist/commands/spine-llm-replay.test.d.ts +2 -0
- package/dist/commands/spine-llm-replay.test.d.ts.map +1 -0
- package/dist/commands/spine-llm-replay.test.js +372 -0
- package/dist/commands/spine-llm-replay.test.js.map +1 -0
- package/dist/commands/spine-review-thread-source.d.ts +165 -0
- package/dist/commands/spine-review-thread-source.d.ts.map +1 -0
- package/dist/commands/spine-review-thread-source.js +251 -0
- package/dist/commands/spine-review-thread-source.js.map +1 -0
- package/dist/commands/spine-review-thread-source.test.d.ts +2 -0
- package/dist/commands/spine-review-thread-source.test.d.ts.map +1 -0
- package/dist/commands/spine-review-thread-source.test.js +284 -0
- package/dist/commands/spine-review-thread-source.test.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ADR-111 Stage-1 Extract — the live CLI `ReviewThreadSource` adapter (slice 5a,
|
|
3
|
+
* mmnto-ai/totem#2201).
|
|
4
|
+
*
|
|
5
|
+
* Core defines the `ReviewThreadSource` port and stays network-free + LLM-free +
|
|
6
|
+
* deterministic; THIS file is the IO-at-the-edge implementation that wraps the
|
|
7
|
+
* GitHub GraphQL `reviewThreads` API behind that port. It fetches a PR's merge
|
|
8
|
+
* commit + its review threads (each carrying `isResolved` / `isOutdated`), maps
|
|
9
|
+
* them to the provider-neutral `ReviewThreadContent`, and SURFACES the per-thread
|
|
10
|
+
* resolution flags to core. It does NOT filter resolved/outdated threads — the
|
|
11
|
+
* contract-owner ruling is "surface, don't filter": core decides eligibility and
|
|
12
|
+
* drop-ledgers every rejection (§8 "every rejection ledgered"). A server-side or
|
|
13
|
+
* client-side `isResolved:false` pre-filter is FORBIDDEN here.
|
|
14
|
+
*
|
|
15
|
+
* Error contract (the discriminated `FetchResult`, §6): a per-PR failure is NEVER
|
|
16
|
+
* thrown — the orchestrator iterates the whole train slice and must not abort on
|
|
17
|
+
* one bad PR. Network / not-found → `{kind:'unreachable'}`; a malformed or
|
|
18
|
+
* unmappable payload → `{kind:'unparseable'}`. The mining run continues; the loud
|
|
19
|
+
* drop is core's job.
|
|
20
|
+
*
|
|
21
|
+
* Reuses the established `gh` CLI exec pattern (Tenet-21 — no bespoke GraphQL
|
|
22
|
+
* client). The `exec` seam is injectable so the query-spy + mapping tests run
|
|
23
|
+
* fully offline (no network, CI-locked).
|
|
24
|
+
*/
|
|
25
|
+
import { z } from 'zod';
|
|
26
|
+
// ─── Named constants ─────────────────────────────────
|
|
27
|
+
/** gh exec timeout (ms). */
|
|
28
|
+
const GH_TIMEOUT_MS = 60_000;
|
|
29
|
+
/** 10MB — handles large review-thread payloads without ENOBUFS. */
|
|
30
|
+
const GH_MAX_BUFFER = 10 * 1024 * 1024;
|
|
31
|
+
/**
|
|
32
|
+
* Page size for `reviewThreads(first:)` / `comments(first:)`. A single page is
|
|
33
|
+
* fetched; if GitHub reports more, the adapter fails LOUD (`unparseable`) rather
|
|
34
|
+
* than silently truncating the corpus (§6 no-silent-shrink). The Gate-1 corpus
|
|
35
|
+
* PRs are small reviewed PRs, comfortably within one page.
|
|
36
|
+
*
|
|
37
|
+
* TODO(#2199): paginate reviewThreads/comments past one page if a future corpus
|
|
38
|
+
* PR ever exceeds PAGE_SIZE.
|
|
39
|
+
*/
|
|
40
|
+
const PAGE_SIZE = 100;
|
|
41
|
+
// ─── GraphQL response schema (Zod at the IO boundary only) ───────────────────
|
|
42
|
+
const PageInfoSchema = z.object({ hasNextPage: z.boolean() });
|
|
43
|
+
const GqlCommentSchema = z.object({
|
|
44
|
+
// `author` is null for deleted/ghost accounts — coerce downstream to ''.
|
|
45
|
+
author: z.object({ login: z.string() }).nullable(),
|
|
46
|
+
body: z.string(),
|
|
47
|
+
});
|
|
48
|
+
const GqlReviewThreadSchema = z.object({
|
|
49
|
+
isResolved: z.boolean(),
|
|
50
|
+
isOutdated: z.boolean(),
|
|
51
|
+
path: z.string(),
|
|
52
|
+
comments: z.object({
|
|
53
|
+
pageInfo: PageInfoSchema,
|
|
54
|
+
nodes: z.array(GqlCommentSchema),
|
|
55
|
+
}),
|
|
56
|
+
});
|
|
57
|
+
const GqlResponseSchema = z.object({
|
|
58
|
+
data: z.object({
|
|
59
|
+
repository: z
|
|
60
|
+
.object({
|
|
61
|
+
pullRequest: z
|
|
62
|
+
.object({
|
|
63
|
+
mergeCommit: z.object({ oid: z.string() }).nullable(),
|
|
64
|
+
reviewThreads: z.object({
|
|
65
|
+
pageInfo: PageInfoSchema,
|
|
66
|
+
nodes: z.array(GqlReviewThreadSchema),
|
|
67
|
+
}),
|
|
68
|
+
})
|
|
69
|
+
.nullable(),
|
|
70
|
+
})
|
|
71
|
+
.nullable(),
|
|
72
|
+
}),
|
|
73
|
+
});
|
|
74
|
+
// ─── Query construction (structurally requests isResolved + isOutdated) ──────
|
|
75
|
+
/**
|
|
76
|
+
* Build the `reviewThreads` GraphQL query. It REQUESTS `isResolved` and
|
|
77
|
+
* `isOutdated` per thread (so core HAS the signal to decide on) — it deliberately
|
|
78
|
+
* does NOT add an `isResolved: false` server-side filter (the "surface, don't
|
|
79
|
+
* filter" ruling; the query-spy test asserts both halves). Exported for the
|
|
80
|
+
* query-spy test.
|
|
81
|
+
*/
|
|
82
|
+
export function buildReviewThreadsQuery(owner, name, pr) {
|
|
83
|
+
return `query {
|
|
84
|
+
repository(owner: ${JSON.stringify(owner)}, name: ${JSON.stringify(name)}) {
|
|
85
|
+
pullRequest(number: ${pr}) {
|
|
86
|
+
mergeCommit { oid }
|
|
87
|
+
reviewThreads(first: ${PAGE_SIZE}) {
|
|
88
|
+
pageInfo { hasNextPage }
|
|
89
|
+
nodes {
|
|
90
|
+
isResolved
|
|
91
|
+
isOutdated
|
|
92
|
+
path
|
|
93
|
+
comments(first: ${PAGE_SIZE}) {
|
|
94
|
+
pageInfo { hasNextPage }
|
|
95
|
+
nodes {
|
|
96
|
+
author { login }
|
|
97
|
+
body
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}`;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Lazy-load `safeExec` and bind it to a `gh`-backed `GhExec` for `cwd`. The
|
|
108
|
+
* dynamic import keeps the heavy core barrel off the CLI startup path (the
|
|
109
|
+
* spine-windtunnel.ts convention).
|
|
110
|
+
*/
|
|
111
|
+
async function loadDefaultExec(cwd) {
|
|
112
|
+
const { safeExec } = await import('@mmnto/totem');
|
|
113
|
+
return (command, args) => safeExec(command, args, {
|
|
114
|
+
cwd,
|
|
115
|
+
timeout: GH_TIMEOUT_MS,
|
|
116
|
+
maxBuffer: GH_MAX_BUFFER,
|
|
117
|
+
env: { ...process.env, GH_PROMPT_DISABLED: '1' },
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
// ─── Mapping ─────────────────────────────────────────
|
|
121
|
+
/**
|
|
122
|
+
* Map a validated GraphQL response to the surviving `ReviewThread[]` with their
|
|
123
|
+
* resolution flags surfaced. Pure — exported for the mapping test. A null author
|
|
124
|
+
* (deleted/ghost) coerces to '' (`isBotIdentity('')` is false, so it stays a
|
|
125
|
+
* human-author '' that core's empty-body / count logic handles correctly; the
|
|
126
|
+
* body still gates inclusion).
|
|
127
|
+
*/
|
|
128
|
+
export function mapThreads(nodes) {
|
|
129
|
+
return nodes.map((t) => ({
|
|
130
|
+
path: t.path,
|
|
131
|
+
// SURFACE the flags — never filter on them here (core decides).
|
|
132
|
+
isResolved: t.isResolved,
|
|
133
|
+
isOutdated: t.isOutdated,
|
|
134
|
+
comments: t.comments.nodes.map((c) => ({
|
|
135
|
+
author: c.author?.login ?? '',
|
|
136
|
+
body: c.body,
|
|
137
|
+
})),
|
|
138
|
+
}));
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* The live `ReviewThreadSource`. Constructible + exported now (slice 5a); wiring
|
|
142
|
+
* it into the spine orchestrator's `run` command is slice 5c.
|
|
143
|
+
*/
|
|
144
|
+
export class ReviewThreadSourceAdapter {
|
|
145
|
+
owner;
|
|
146
|
+
name;
|
|
147
|
+
cwd;
|
|
148
|
+
/** Injected exec seam (tests); when absent the default is lazy-loaded once via `execPromise`. */
|
|
149
|
+
injectedExec;
|
|
150
|
+
/**
|
|
151
|
+
* Memoized lazy-load of the default `gh`-backed exec (real runs). Memoizes the
|
|
152
|
+
* PROMISE, not the resolved value, so concurrent `fetch()` calls on one adapter
|
|
153
|
+
* instance share a single `loadDefaultExec` instead of racing a `!this.exec`
|
|
154
|
+
* guard (CR #2207 — was benign since dynamic import is idempotent, now explicit).
|
|
155
|
+
*/
|
|
156
|
+
execPromise;
|
|
157
|
+
constructor(opts) {
|
|
158
|
+
this.owner = opts.owner;
|
|
159
|
+
this.name = opts.name;
|
|
160
|
+
this.cwd = opts.cwd ?? process.cwd();
|
|
161
|
+
this.injectedExec = opts.exec;
|
|
162
|
+
}
|
|
163
|
+
/** Resolve the exec seam: the injected one (tests), else the memoized lazy-loaded default. */
|
|
164
|
+
resolveExec() {
|
|
165
|
+
if (this.injectedExec)
|
|
166
|
+
return Promise.resolve(this.injectedExec);
|
|
167
|
+
this.execPromise ??= loadDefaultExec(this.cwd);
|
|
168
|
+
return this.execPromise;
|
|
169
|
+
}
|
|
170
|
+
async fetch(pr) {
|
|
171
|
+
const query = buildReviewThreadsQuery(this.owner, this.name, pr);
|
|
172
|
+
const exec = await this.resolveExec();
|
|
173
|
+
// totem-context: this catch does NOT silently degrade — it is the §6 port
|
|
174
|
+
// contract. A per-PR IO failure (network/404/auth) is reified into the
|
|
175
|
+
// discriminated FetchResult ('unreachable') and surfaced LOUDLY to core,
|
|
176
|
+
// which drop-ledgers it (a creditable FM-i drop). Re-throwing would abort the
|
|
177
|
+
// whole mining run on one bad PR, violating the orchestrator's train-slice
|
|
178
|
+
// sweep. The loud-fail lives in core's ledger, not a thrown exception.
|
|
179
|
+
let raw;
|
|
180
|
+
try {
|
|
181
|
+
raw = exec('gh', ['api', 'graphql', '-f', `query=${query}`]);
|
|
182
|
+
// totem-context: intentional §6 port contract — reify IO failure into the discriminated FetchResult, surfaced loudly to core's drop ledger; never swallowed.
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
return {
|
|
186
|
+
kind: 'unreachable',
|
|
187
|
+
detail: `gh graphql fetch failed for PR #${pr}: ${err instanceof Error ? err.message : String(err)}`,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
// totem-context: intentional — same §6 port contract as above. A malformed /
|
|
191
|
+
// unmappable payload is reified into FetchResult ('unparseable', a route
|
|
192
|
+
// distinct from 'unreachable') and surfaced LOUDLY to core for drop-ledgering,
|
|
193
|
+
// not swallowed. Re-throwing would abort the orchestrator's whole train-slice
|
|
194
|
+
// sweep on one bad payload.
|
|
195
|
+
let parsed;
|
|
196
|
+
try {
|
|
197
|
+
parsed = GqlResponseSchema.parse(JSON.parse(raw));
|
|
198
|
+
// totem-context: intentional §6 port contract — reify the unparseable payload into the discriminated FetchResult, surfaced loudly to core's drop ledger; never swallowed.
|
|
199
|
+
}
|
|
200
|
+
catch (err) {
|
|
201
|
+
return {
|
|
202
|
+
kind: 'unparseable',
|
|
203
|
+
detail: `review-thread payload unparseable for PR #${pr}: ${err instanceof Error ? err.message : String(err)}`,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
// Distinguish a null repository (repo inaccessible / token lacks scope) from a
|
|
207
|
+
// null pullRequest (PR genuinely not found): both are `unreachable`, but they
|
|
208
|
+
// need different diagnostic leads, so the detail strings differ (CR + Greptile
|
|
209
|
+
// #2207 — a shared `!pull` guard would send a token-scope failure chasing a
|
|
210
|
+
// non-existent PR).
|
|
211
|
+
const repo = parsed.data.repository;
|
|
212
|
+
if (!repo) {
|
|
213
|
+
return {
|
|
214
|
+
kind: 'unreachable',
|
|
215
|
+
detail: `repository ${this.owner}/${this.name} not found or inaccessible (check owner/name + token scope) while fetching PR #${pr}`,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
const pull = repo.pullRequest;
|
|
219
|
+
if (!pull) {
|
|
220
|
+
return { kind: 'unreachable', detail: `PR #${pr} not found in ${this.owner}/${this.name}` };
|
|
221
|
+
}
|
|
222
|
+
// A merged train PR MUST have a merge commit (the provenance SHA core needs).
|
|
223
|
+
// Its absence is an unusable payload, not a fetch failure → 'unparseable'.
|
|
224
|
+
const mergeCommitSha = pull.mergeCommit?.oid?.toLowerCase();
|
|
225
|
+
if (!mergeCommitSha) {
|
|
226
|
+
return { kind: 'unparseable', detail: `PR #${pr} has no merge commit oid` };
|
|
227
|
+
}
|
|
228
|
+
// No-silent-shrink (§6): if the payload was paginated past one page, fail
|
|
229
|
+
// LOUD rather than mining a partial thread set.
|
|
230
|
+
if (pull.reviewThreads.pageInfo.hasNextPage) {
|
|
231
|
+
return {
|
|
232
|
+
kind: 'unparseable',
|
|
233
|
+
detail: `PR #${pr} has more than ${PAGE_SIZE} review threads (pagination unsupported)`,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
for (const t of pull.reviewThreads.nodes) {
|
|
237
|
+
if (t.comments.pageInfo.hasNextPage) {
|
|
238
|
+
return {
|
|
239
|
+
kind: 'unparseable',
|
|
240
|
+
detail: `PR #${pr} has a review thread with more than ${PAGE_SIZE} comments (pagination unsupported)`,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const threads = mapThreads(pull.reviewThreads.nodes);
|
|
245
|
+
return {
|
|
246
|
+
kind: 'ok',
|
|
247
|
+
content: { pr, mergeCommitSha, threads },
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=spine-review-thread-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spine-review-thread-source.js","sourceRoot":"","sources":["../../src/commands/spine-review-thread-source.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spine-review-thread-source.test.d.ts","sourceRoot":"","sources":["../../src/commands/spine-review-thread-source.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { buildReviewThreadsQuery, mapThreads, ReviewThreadSourceAdapter, } from './spine-review-thread-source.js';
|
|
3
|
+
// ─── Helpers ─────────────────────────────────────────
|
|
4
|
+
const OWNER = 'mmnto-ai';
|
|
5
|
+
const NAME = 'totem';
|
|
6
|
+
const MERGE_OID = 'a'.repeat(40);
|
|
7
|
+
/** A well-formed GraphQL response payload (string, as `gh` returns). */
|
|
8
|
+
function okPayload(opts) {
|
|
9
|
+
const threads = (opts?.threads ?? []).map((t) => ({
|
|
10
|
+
isResolved: t.isResolved ?? false,
|
|
11
|
+
isOutdated: t.isOutdated ?? false,
|
|
12
|
+
path: t.path ?? 'packages/core/src/x.ts',
|
|
13
|
+
comments: {
|
|
14
|
+
pageInfo: { hasNextPage: t.commentsHasNext ?? false },
|
|
15
|
+
nodes: (t.comments ?? [{ login: 'jane', body: 'a note' }]).map((c) => ({
|
|
16
|
+
author: c.login === null ? null : { login: c.login },
|
|
17
|
+
body: c.body,
|
|
18
|
+
})),
|
|
19
|
+
},
|
|
20
|
+
}));
|
|
21
|
+
return JSON.stringify({
|
|
22
|
+
data: {
|
|
23
|
+
repository: {
|
|
24
|
+
pullRequest: {
|
|
25
|
+
mergeCommit: opts?.mergeOid === null ? null : { oid: opts?.mergeOid ?? MERGE_OID },
|
|
26
|
+
reviewThreads: {
|
|
27
|
+
pageInfo: { hasNextPage: opts?.threadsHasNext ?? false },
|
|
28
|
+
nodes: threads,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/** An exec stub that records the args it was called with and returns a fixed payload. */
|
|
36
|
+
function stubExec(payload) {
|
|
37
|
+
const calls = [];
|
|
38
|
+
const fn = ((_command, args) => {
|
|
39
|
+
calls.push(args);
|
|
40
|
+
return payload;
|
|
41
|
+
});
|
|
42
|
+
fn.calls = calls;
|
|
43
|
+
return fn;
|
|
44
|
+
}
|
|
45
|
+
// ─── Query construction (the reframed agy fold-2: query-spy) ─────────────────
|
|
46
|
+
describe('buildReviewThreadsQuery', () => {
|
|
47
|
+
it('REQUESTS isResolved and isOutdated on reviewThreads (so core has the signal)', () => {
|
|
48
|
+
const q = buildReviewThreadsQuery(OWNER, NAME, 42);
|
|
49
|
+
expect(q).toContain('reviewThreads');
|
|
50
|
+
expect(q).toContain('isResolved');
|
|
51
|
+
expect(q).toContain('isOutdated');
|
|
52
|
+
expect(q).toContain('mergeCommit');
|
|
53
|
+
});
|
|
54
|
+
it('does NOT pre-filter with isResolved:false — surface, not filter (contract B)', () => {
|
|
55
|
+
const q = buildReviewThreadsQuery(OWNER, NAME, 42);
|
|
56
|
+
// The "surface, don't filter" ruling: no server-side resolution filter.
|
|
57
|
+
expect(q).not.toMatch(/isResolved\s*:\s*false/);
|
|
58
|
+
// requestArguments use parentheses, e.g. reviewThreads(first: 100) — there
|
|
59
|
+
// must be no boolean argument predicate on isResolved.
|
|
60
|
+
expect(q).not.toMatch(/reviewThreads\([^)]*isResolved/);
|
|
61
|
+
});
|
|
62
|
+
it('embeds owner/name as JSON-escaped strings and the numeric PR', () => {
|
|
63
|
+
const q = buildReviewThreadsQuery(OWNER, NAME, 7);
|
|
64
|
+
expect(q).toContain('owner: "mmnto-ai"');
|
|
65
|
+
expect(q).toContain('name: "totem"');
|
|
66
|
+
expect(q).toContain('pullRequest(number: 7)');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
describe('ReviewThreadSourceAdapter — query-spy through fetch', () => {
|
|
70
|
+
it('passes a query that requests the resolution fields to gh', async () => {
|
|
71
|
+
const exec = stubExec(okPayload({ threads: [{}] }));
|
|
72
|
+
const adapter = new ReviewThreadSourceAdapter({ owner: OWNER, name: NAME, exec });
|
|
73
|
+
await adapter.fetch(99);
|
|
74
|
+
expect(exec.calls).toHaveLength(1);
|
|
75
|
+
const args = exec.calls[0];
|
|
76
|
+
expect(args[0]).toBe('api');
|
|
77
|
+
expect(args[1]).toBe('graphql');
|
|
78
|
+
const queryArg = args.find((a) => a.startsWith('query='));
|
|
79
|
+
expect(queryArg).toBeDefined();
|
|
80
|
+
expect(queryArg).toContain('isResolved');
|
|
81
|
+
expect(queryArg).toContain('isOutdated');
|
|
82
|
+
expect(queryArg).not.toMatch(/reviewThreads\([^)]*isResolved/);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
// ─── Mapping ─────────────────────────────────────────
|
|
86
|
+
describe('mapThreads', () => {
|
|
87
|
+
it('surfaces per-thread isResolved/isOutdated flags (does not filter)', () => {
|
|
88
|
+
const mapped = mapThreads([
|
|
89
|
+
{
|
|
90
|
+
isResolved: true,
|
|
91
|
+
isOutdated: false,
|
|
92
|
+
path: 'a.ts',
|
|
93
|
+
comments: {
|
|
94
|
+
pageInfo: { hasNextPage: false },
|
|
95
|
+
nodes: [{ author: { login: 'jane' }, body: 'x' }],
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
isResolved: false,
|
|
100
|
+
isOutdated: true,
|
|
101
|
+
path: 'b.ts',
|
|
102
|
+
comments: {
|
|
103
|
+
pageInfo: { hasNextPage: false },
|
|
104
|
+
nodes: [{ author: { login: 'john' }, body: 'y' }],
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
]);
|
|
108
|
+
// BOTH threads are present — nothing filtered out (surface, not filter).
|
|
109
|
+
expect(mapped).toHaveLength(2);
|
|
110
|
+
expect(mapped[0]).toMatchObject({ path: 'a.ts', isResolved: true, isOutdated: false });
|
|
111
|
+
expect(mapped[1]).toMatchObject({ path: 'b.ts', isResolved: false, isOutdated: true });
|
|
112
|
+
});
|
|
113
|
+
it('coerces a null author (deleted/ghost) to an empty login', () => {
|
|
114
|
+
const mapped = mapThreads([
|
|
115
|
+
{
|
|
116
|
+
isResolved: false,
|
|
117
|
+
isOutdated: false,
|
|
118
|
+
path: 'a.ts',
|
|
119
|
+
comments: {
|
|
120
|
+
pageInfo: { hasNextPage: false },
|
|
121
|
+
nodes: [{ author: null, body: 'ghost note' }],
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
]);
|
|
125
|
+
expect(mapped[0].comments[0].author).toBe('');
|
|
126
|
+
expect(mapped[0].comments[0].body).toBe('ghost note');
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
// ─── fetch() — payload → ReviewThreadContent + failure mapping ────────────────
|
|
130
|
+
describe('ReviewThreadSourceAdapter.fetch — success mapping', () => {
|
|
131
|
+
it('maps a GraphQL payload to ReviewThreadContent with per-thread flags', async () => {
|
|
132
|
+
const exec = stubExec(okPayload({
|
|
133
|
+
mergeOid: MERGE_OID,
|
|
134
|
+
threads: [
|
|
135
|
+
{
|
|
136
|
+
isResolved: false,
|
|
137
|
+
isOutdated: false,
|
|
138
|
+
path: 'x.ts',
|
|
139
|
+
comments: [{ login: 'jane', body: 'eligible' }],
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
isResolved: true,
|
|
143
|
+
isOutdated: false,
|
|
144
|
+
path: 'y.ts',
|
|
145
|
+
comments: [{ login: 'john', body: 'resolved' }],
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
}));
|
|
149
|
+
const adapter = new ReviewThreadSourceAdapter({ owner: OWNER, name: NAME, exec });
|
|
150
|
+
const result = await adapter.fetch(123);
|
|
151
|
+
expect(result.kind).toBe('ok');
|
|
152
|
+
if (result.kind !== 'ok')
|
|
153
|
+
return;
|
|
154
|
+
expect(result.content.pr).toBe(123);
|
|
155
|
+
expect(result.content.mergeCommitSha).toBe(MERGE_OID);
|
|
156
|
+
expect(result.content.threads).toHaveLength(2);
|
|
157
|
+
expect(result.content.threads[0]).toMatchObject({ isResolved: false, isOutdated: false });
|
|
158
|
+
expect(result.content.threads[1]).toMatchObject({ isResolved: true, isOutdated: false });
|
|
159
|
+
});
|
|
160
|
+
it('lowercases the merge commit oid (provenance canonical form)', async () => {
|
|
161
|
+
const exec = stubExec(okPayload({ mergeOid: 'A'.repeat(40), threads: [{}] }));
|
|
162
|
+
const adapter = new ReviewThreadSourceAdapter({ owner: OWNER, name: NAME, exec });
|
|
163
|
+
const result = await adapter.fetch(1);
|
|
164
|
+
expect(result.kind).toBe('ok');
|
|
165
|
+
if (result.kind !== 'ok')
|
|
166
|
+
return;
|
|
167
|
+
expect(result.content.mergeCommitSha).toBe('a'.repeat(40));
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
describe('ReviewThreadSourceAdapter.fetch — failure mapping (§6 discriminated)', () => {
|
|
171
|
+
it('a thrown gh error (network/404/auth) maps to unreachable, never throws', async () => {
|
|
172
|
+
// totem-context: this `new Error` SIMULATES an external `gh`/network throw the
|
|
173
|
+
// adapter must catch — it is the third-party error under test, not a
|
|
174
|
+
// Totem-originated one, so it deliberately carries no [Totem Error] prefix.
|
|
175
|
+
const throwingExec = () => {
|
|
176
|
+
throw new Error('gh: HTTP 404: Not Found');
|
|
177
|
+
};
|
|
178
|
+
const adapter = new ReviewThreadSourceAdapter({ owner: OWNER, name: NAME, exec: throwingExec });
|
|
179
|
+
const result = await adapter.fetch(404);
|
|
180
|
+
expect(result.kind).toBe('unreachable');
|
|
181
|
+
if (result.kind === 'unreachable')
|
|
182
|
+
expect(result.detail).toContain('404');
|
|
183
|
+
});
|
|
184
|
+
it('invalid JSON maps to unparseable, never throws', async () => {
|
|
185
|
+
const adapter = new ReviewThreadSourceAdapter({
|
|
186
|
+
owner: OWNER,
|
|
187
|
+
name: NAME,
|
|
188
|
+
exec: stubExec('not json at all'),
|
|
189
|
+
});
|
|
190
|
+
const result = await adapter.fetch(1);
|
|
191
|
+
expect(result.kind).toBe('unparseable');
|
|
192
|
+
});
|
|
193
|
+
it('a schema-mismatched payload maps to unparseable', async () => {
|
|
194
|
+
const adapter = new ReviewThreadSourceAdapter({
|
|
195
|
+
owner: OWNER,
|
|
196
|
+
name: NAME,
|
|
197
|
+
exec: stubExec(JSON.stringify({ data: { repository: { pullRequest: { wrong: true } } } })),
|
|
198
|
+
});
|
|
199
|
+
const result = await adapter.fetch(1);
|
|
200
|
+
expect(result.kind).toBe('unparseable');
|
|
201
|
+
});
|
|
202
|
+
it('a missing pullRequest maps to unreachable (PR not found)', async () => {
|
|
203
|
+
const adapter = new ReviewThreadSourceAdapter({
|
|
204
|
+
owner: OWNER,
|
|
205
|
+
name: NAME,
|
|
206
|
+
exec: stubExec(JSON.stringify({ data: { repository: { pullRequest: null } } })),
|
|
207
|
+
});
|
|
208
|
+
const result = await adapter.fetch(1);
|
|
209
|
+
expect(result.kind).toBe('unreachable');
|
|
210
|
+
// PR-not-found detail names the PR, not the repository (CR + Greptile #2207).
|
|
211
|
+
if (result.kind === 'unreachable')
|
|
212
|
+
expect(result.detail).toContain('not found in');
|
|
213
|
+
});
|
|
214
|
+
it('a null repository (inaccessible / token scope) maps to unreachable with a repo-specific detail', async () => {
|
|
215
|
+
const adapter = new ReviewThreadSourceAdapter({
|
|
216
|
+
owner: OWNER,
|
|
217
|
+
name: NAME,
|
|
218
|
+
exec: stubExec(JSON.stringify({ data: { repository: null } })),
|
|
219
|
+
});
|
|
220
|
+
const result = await adapter.fetch(1);
|
|
221
|
+
expect(result.kind).toBe('unreachable');
|
|
222
|
+
// Distinct from PR-not-found: the detail leads with the repository, not the PR
|
|
223
|
+
// (CR + Greptile #2207 — don't send a token-scope failure chasing a missing PR).
|
|
224
|
+
if (result.kind === 'unreachable') {
|
|
225
|
+
expect(result.detail).toContain('repository');
|
|
226
|
+
expect(result.detail).toContain('token scope');
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
it('a null merge commit (unmerged / missing) maps to unparseable', async () => {
|
|
230
|
+
const adapter = new ReviewThreadSourceAdapter({
|
|
231
|
+
owner: OWNER,
|
|
232
|
+
name: NAME,
|
|
233
|
+
exec: stubExec(okPayload({ mergeOid: null, threads: [{}] })),
|
|
234
|
+
});
|
|
235
|
+
const result = await adapter.fetch(1);
|
|
236
|
+
expect(result.kind).toBe('unparseable');
|
|
237
|
+
if (result.kind === 'unparseable')
|
|
238
|
+
expect(result.detail).toContain('merge commit');
|
|
239
|
+
});
|
|
240
|
+
it('paginated review threads fail loud as unparseable (no silent shrink)', async () => {
|
|
241
|
+
const adapter = new ReviewThreadSourceAdapter({
|
|
242
|
+
owner: OWNER,
|
|
243
|
+
name: NAME,
|
|
244
|
+
exec: stubExec(okPayload({ threads: [{}], threadsHasNext: true })),
|
|
245
|
+
});
|
|
246
|
+
const result = await adapter.fetch(1);
|
|
247
|
+
expect(result.kind).toBe('unparseable');
|
|
248
|
+
if (result.kind === 'unparseable')
|
|
249
|
+
expect(result.detail).toContain('review threads');
|
|
250
|
+
});
|
|
251
|
+
it('paginated comments within a thread fail loud as unparseable', async () => {
|
|
252
|
+
const adapter = new ReviewThreadSourceAdapter({
|
|
253
|
+
owner: OWNER,
|
|
254
|
+
name: NAME,
|
|
255
|
+
exec: stubExec(okPayload({ threads: [{ commentsHasNext: true }] })),
|
|
256
|
+
});
|
|
257
|
+
const result = await adapter.fetch(1);
|
|
258
|
+
expect(result.kind).toBe('unparseable');
|
|
259
|
+
if (result.kind === 'unparseable')
|
|
260
|
+
expect(result.detail).toContain('comments');
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
describe('ReviewThreadSourceAdapter.fetch — determinism', () => {
|
|
264
|
+
it('identical payload → identical FetchResult', async () => {
|
|
265
|
+
const payload = okPayload({
|
|
266
|
+
threads: [
|
|
267
|
+
{ isResolved: false, comments: [{ login: 'jane', body: 'a' }] },
|
|
268
|
+
{ isResolved: true, comments: [{ login: 'john', body: 'b' }] },
|
|
269
|
+
],
|
|
270
|
+
});
|
|
271
|
+
const a = await new ReviewThreadSourceAdapter({
|
|
272
|
+
owner: OWNER,
|
|
273
|
+
name: NAME,
|
|
274
|
+
exec: stubExec(payload),
|
|
275
|
+
}).fetch(5);
|
|
276
|
+
const b = await new ReviewThreadSourceAdapter({
|
|
277
|
+
owner: OWNER,
|
|
278
|
+
name: NAME,
|
|
279
|
+
exec: stubExec(payload),
|
|
280
|
+
}).fetch(5);
|
|
281
|
+
expect(a).toEqual(b);
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
//# sourceMappingURL=spine-review-thread-source.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spine-review-thread-source.test.js","sourceRoot":"","sources":["../../src/commands/spine-review-thread-source.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mmnto/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.69.0",
|
|
4
4
|
"description": "CLI for Totem — AI persistent memory and context layer",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"smol-toml": "^1.6.1",
|
|
29
29
|
"yaml": "^2.4.0",
|
|
30
30
|
"zod": "^3.24.0",
|
|
31
|
-
"@mmnto/totem": "1.
|
|
31
|
+
"@mmnto/totem": "1.69.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@anthropic-ai/sdk": "^0.98.0",
|