gaunt-sloth 2.0.0-beta.8 → 2.0.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/.gsloth.review-discovery.md +19 -0
- package/cli.js +49 -0
- package/dist/cli.js +37 -3
- package/dist/cli.js.map +1 -1
- package/dist/commands/adkEvalRunner.d.ts +7 -6
- package/dist/commands/adkEvalRunner.js +3 -3
- package/dist/commands/adkEvalRunner.js.map +1 -1
- package/dist/commands/agUiEvalRunner.d.ts +4 -4
- package/dist/commands/agUiEvalRunner.js +8 -7
- package/dist/commands/agUiEvalRunner.js.map +1 -1
- package/dist/commands/askCommand.js +9 -1
- package/dist/commands/askCommand.js.map +1 -1
- package/dist/commands/batchCommand.d.ts +2 -2
- package/dist/commands/batchCommand.js +10 -5
- package/dist/commands/batchCommand.js.map +1 -1
- package/dist/commands/commandIntrospection.d.ts +1 -1
- package/dist/commands/commandIntrospection.js +6 -3
- package/dist/commands/commandIntrospection.js.map +1 -1
- package/dist/commands/configCommand.d.ts +1 -1
- package/dist/commands/configCommand.js +1 -1
- package/dist/commands/configSetup.d.ts +1 -1
- package/dist/commands/discoveryConfigSchemaAgreement.d.ts +45 -0
- package/dist/commands/discoveryConfigSchemaAgreement.js +2 -0
- package/dist/commands/discoveryConfigSchemaAgreement.js.map +1 -0
- package/dist/commands/evalCommand.d.ts +27 -1
- package/dist/commands/evalCommand.js +155 -13
- package/dist/commands/evalCommand.js.map +1 -1
- package/dist/commands/execCommand.d.ts +1 -1
- package/dist/commands/execCommand.js +9 -2
- package/dist/commands/execCommand.js.map +1 -1
- package/dist/commands/firstRunDialog.d.ts +3 -3
- package/dist/commands/firstRunDialog.js +2 -2
- package/dist/commands/getCommand.js +10 -1
- package/dist/commands/getCommand.js.map +1 -1
- package/dist/commands/historyCommand.d.ts +1 -1
- package/dist/commands/historyCommand.js +16 -4
- package/dist/commands/historyCommand.js.map +1 -1
- package/dist/commands/prCommand.js +45 -16
- package/dist/commands/prCommand.js.map +1 -1
- package/dist/commands/prDiscovery.d.ts +24 -25
- package/dist/commands/prDiscovery.js +55 -132
- package/dist/commands/prDiscovery.js.map +1 -1
- package/dist/commands/requirementsDiscovery.d.ts +82 -0
- package/dist/commands/requirementsDiscovery.js +127 -0
- package/dist/commands/requirementsDiscovery.js.map +1 -0
- package/dist/commands/reviewCommand.js +75 -8
- package/dist/commands/reviewCommand.js.map +1 -1
- package/dist/commands/reviewDiscovery.d.ts +96 -0
- package/dist/commands/reviewDiscovery.js +180 -0
- package/dist/commands/reviewDiscovery.js.map +1 -0
- package/dist/tui/approvalBridges.d.ts +86 -0
- package/dist/tui/approvalBridges.js +147 -0
- package/dist/tui/approvalBridges.js.map +1 -0
- package/dist/tui/components/App.js +272 -27
- package/dist/tui/components/App.js.map +1 -1
- package/dist/tui/components/DebugPanel.d.ts +6 -3
- package/dist/tui/components/DebugPanel.js +32 -10
- package/dist/tui/components/DebugPanel.js.map +1 -1
- package/dist/tui/components/FetchProgress.d.ts +1 -1
- package/dist/tui/components/LaunchBanner.d.ts +4 -3
- package/dist/tui/components/LaunchBanner.js +8 -6
- package/dist/tui/components/LaunchBanner.js.map +1 -1
- package/dist/tui/components/LiveTurn.d.ts +15 -9
- package/dist/tui/components/LiveTurn.js +15 -14
- package/dist/tui/components/LiveTurn.js.map +1 -1
- package/dist/tui/components/PromptInput.d.ts +2 -2
- package/dist/tui/components/PromptInput.js +11 -6
- package/dist/tui/components/PromptInput.js.map +1 -1
- package/dist/tui/components/ResumePicker.d.ts +69 -0
- package/dist/tui/components/ResumePicker.js +93 -0
- package/dist/tui/components/ResumePicker.js.map +1 -0
- package/dist/tui/components/SelectList.d.ts +1 -1
- package/dist/tui/components/SelectList.js +1 -1
- package/dist/tui/components/SlashCommandMenu.d.ts +1 -1
- package/dist/tui/components/SlashCommandMenu.js +1 -1
- package/dist/tui/components/StatusBar.d.ts +27 -1
- package/dist/tui/components/StatusBar.js +13 -2
- package/dist/tui/components/StatusBar.js.map +1 -1
- package/dist/tui/debugRender.d.ts +26 -3
- package/dist/tui/debugRender.js +232 -2
- package/dist/tui/debugRender.js.map +1 -1
- package/dist/tui/fixtureAgent.d.ts +2 -2
- package/dist/tui/fixtureAgent.js +2 -2
- package/dist/tui/keyBindings.js +7 -1
- package/dist/tui/keyBindings.js.map +1 -1
- package/dist/tui/keyGuards.d.ts +1 -1
- package/dist/tui/keyGuards.js +1 -1
- package/dist/tui/ruleWidth.d.ts +1 -1
- package/dist/tui/ruleWidth.js +1 -1
- package/dist/tui/selectCancelled.d.ts +1 -1
- package/dist/tui/selectCancelled.js +1 -1
- package/dist/tui/transcriptWindow.js +7 -1
- package/dist/tui/transcriptWindow.js.map +1 -1
- package/dist/tui/tuiSessionModule.js +89 -190
- package/dist/tui/tuiSessionModule.js.map +1 -1
- package/dist/tui/types.d.ts +77 -18
- package/dist/tui/useMouse.d.ts +1 -1
- package/dist/tui/useMouse.js +1 -1
- package/dist/tui/useSlothAnimation.d.ts +1 -1
- package/dist/tui/viewModel.d.ts +64 -12
- package/dist/tui/viewModel.js +43 -11
- package/dist/tui/viewModel.js.map +1 -1
- package/dist/utils/configErrorGuard.d.ts +11 -3
- package/dist/utils/configErrorGuard.js +11 -3
- package/dist/utils/configErrorGuard.js.map +1 -1
- package/package.json +18 -18
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getCommand.js","sourceRoot":"","sources":["../../src/commands/getCommand.ts"],"names":[],"mappings":"AACA,OAAO,EAA8B,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACrF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GAIvB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAC;AAErE,MAAM,eAAe,GAAG,
|
|
1
|
+
{"version":3,"file":"getCommand.js","sourceRoot":"","sources":["../../src/commands/getCommand.ts"],"names":[],"mappings":"AACA,OAAO,EAA8B,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACrF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GAIvB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAC;AAErE,MAAM,eAAe,GAAG;IACtB,KAAK;IACL,QAAQ;IACR,IAAI;IACJ,cAAc;IACd,kBAAkB;IAClB,MAAM;IACN,MAAM;IACN,MAAM;CACE,CAAC;AACX,MAAM,eAAe,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAU,CAAC;AAClD,MAAM,WAAW,GAAG,CAAC,SAAS,EAAE,cAAc,CAAU,CAAC;AAEzD,MAAM,UAAU,UAAU,CACxB,OAAgB,EAChB,0BAAsD;IAEtD,OAAO;SACJ,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,2DAA2D,CAAC;SACxE,QAAQ,CAAC,WAAW,EAAE,uBAAuB,CAAC;SAC9C,QAAQ,CAAC,WAAW,EAAE,yCAAyC,CAAC;SAChE,QAAQ,CAAC,MAAM,EAAE,kCAAkC,CAAC;SACpD,WAAW,CACV,OAAO,EACP,IAAI,GAAG,aAAa,GAAG,6BAA6B,GAAG,6BAA6B,CACrF;SACA,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,OAAe,EAAE,EAAsB,EAAE,EAAE;QACzE,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,0BAA0B,CAAC,CAAC;YAE5D,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;gBACzB,IAAI,EAAE,EAAE,CAAC;oBACP,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;gBAC3D,CAAC;gBACD,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,OAA4B,CAAC,EAAE,CAAC;oBAC5D,MAAM,IAAI,KAAK,CAAC,+BAA+B,OAAO,GAAG,CAAC,CAAC;gBAC7D,CAAC;gBAED,OAAO,CAAC,sBAAsB,CAAC,OAA4B,EAAE,MAAM,CAAC,CAAC,CAAC;gBACtE,OAAO;YACT,CAAC;YAED,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,OAA0B,CAAC,EAAE,CAAC;gBACtD,MAAM,IAAI,KAAK,CAAC,wBAAwB,OAAO,GAAG,CAAC,CAAC;YACtD,CAAC;YACD,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,OAA4B,CAAC,EAAE,CAAC;gBAC5D,MAAM,IAAI,KAAK,CAAC,sCAAsC,OAAO,GAAG,CAAC,CAAC;YACpE,CAAC;YACD,IAAI,CAAC,EAAE,EAAE,CAAC;gBACR,MAAM,IAAI,KAAK,CAAC,YAAY,OAAO,mBAAmB,CAAC,CAAC;YAC1D,CAAC;YAED,OAAO,CACL,MAAM,qBAAqB,CACzB,OAA4B,EAC5B,OAA0B,EAC1B,EAAE,EACF,MAAM,CACP,CACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACrE,WAAW,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -20,7 +20,7 @@ export declare const NO_HISTORY_MESSAGE: string;
|
|
|
20
20
|
* The first three are READ-ONLY and fail-soft: they open the store with `create: false`, so a
|
|
21
21
|
* missing DB (nothing recorded yet, or history turned off) simply reports "no history yet" instead
|
|
22
22
|
* of materialising an empty file.
|
|
23
|
-
* (Opening still migrates a pre-GS2-19 DB in place — see {@link HistoryStore} migrate.) The DB
|
|
23
|
+
* (Opening still migrates a pre-GS2-19 DB in place — see {@link @gaunt-sloth/core!history/historyStore.HistoryStore | HistoryStore} migrate.) The DB
|
|
24
24
|
* defaults to the global `~/.gsloth/history.db`; `--db <path>` overrides it. Local only — nothing
|
|
25
25
|
* here touches the network.
|
|
26
26
|
*
|
|
@@ -30,7 +30,7 @@ import { sessionConfigFor } from '#src/modules/sessionConfigs.js';
|
|
|
30
30
|
* The first three are READ-ONLY and fail-soft: they open the store with `create: false`, so a
|
|
31
31
|
* missing DB (nothing recorded yet, or history turned off) simply reports "no history yet" instead
|
|
32
32
|
* of materialising an empty file.
|
|
33
|
-
* (Opening still migrates a pre-GS2-19 DB in place — see {@link HistoryStore} migrate.) The DB
|
|
33
|
+
* (Opening still migrates a pre-GS2-19 DB in place — see {@link @gaunt-sloth/core!history/historyStore.HistoryStore | HistoryStore} migrate.) The DB
|
|
34
34
|
* defaults to the global `~/.gsloth/history.db`; `--db <path>` overrides it. Local only — nothing
|
|
35
35
|
* here touches the network.
|
|
36
36
|
*
|
|
@@ -102,8 +102,13 @@ export function historyCommand(program, commandLineConfigOverrides = {}) {
|
|
|
102
102
|
return;
|
|
103
103
|
try {
|
|
104
104
|
const stats = maintenance.stats(dbPath);
|
|
105
|
-
|
|
105
|
+
// GS2-111 — checkpoints are not the whole store. A dropped `put` leaves a thread holding
|
|
106
|
+
// pending writes and no checkpoint: real bytes on disk that only `gth history prune` takes
|
|
107
|
+
// back. A guard on the checkpoint count alone made the one screen that reports the store's
|
|
108
|
+
// size silent about them (DL-1), so this is the pair GS2-108 settled on for `gth insights`.
|
|
109
|
+
if (stats.checkpointCount > 0 || stats.writeOnlyThreadCount > 0) {
|
|
106
110
|
display(formatStoreSizeLine(stats));
|
|
111
|
+
}
|
|
107
112
|
}
|
|
108
113
|
finally {
|
|
109
114
|
maintenance.close();
|
|
@@ -190,11 +195,17 @@ export function historyCommand(program, commandLineConfigOverrides = {}) {
|
|
|
190
195
|
// is how a person finds out how much of the store was never reachable in the first place.
|
|
191
196
|
const unaddressable = maintenance.unaddressable();
|
|
192
197
|
const unaddressableBytes = maintenance.bytesOf(unaddressable);
|
|
198
|
+
// GS2-108 — and so does the write-only set: threads whose pending writes outlived the
|
|
199
|
+
// checkpoint they belonged to. This is the ONLY command that reaches them, because they
|
|
200
|
+
// carry no checkpoint to read an age from and the automatic pass reclaims nothing it
|
|
201
|
+
// cannot date. The reasoning is at `findWriteOnlyThreads`.
|
|
202
|
+
const writeOnly = maintenance.writeOnly();
|
|
203
|
+
const writeOnlyBytes = maintenance.bytesOf(writeOnly);
|
|
193
204
|
displayInfo('History prune:');
|
|
194
|
-
for (const line of formatPrunePlan(candidates, unaddressable.length, unaddressableBytes)) {
|
|
205
|
+
for (const line of formatPrunePlan(candidates, unaddressable.length, unaddressableBytes, writeOnly.length, writeOnlyBytes)) {
|
|
195
206
|
display(line);
|
|
196
207
|
}
|
|
197
|
-
if (candidates.length === 0 && unaddressable.length === 0)
|
|
208
|
+
if (candidates.length === 0 && unaddressable.length === 0 && writeOnly.length === 0)
|
|
198
209
|
return;
|
|
199
210
|
if (!options.yes) {
|
|
200
211
|
displayWarning('Nothing was removed. Re-run with `--yes` to remove it.');
|
|
@@ -204,6 +215,7 @@ export function historyCommand(program, commandLineConfigOverrides = {}) {
|
|
|
204
215
|
const removed = maintenance.remove([
|
|
205
216
|
...candidates.map((c) => c.threadId),
|
|
206
217
|
...unaddressable,
|
|
218
|
+
...writeOnly,
|
|
207
219
|
]);
|
|
208
220
|
const vacuumed = maintenance.vacuum();
|
|
209
221
|
const after = fileBytes(dbPath);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"historyCommand.js","sourceRoot":"","sources":["../../src/commands/historyCommand.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"historyCommand.js","sourceRoot":"","sources":["../../src/commands/historyCommand.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,8 @@ import jiraLogWork from '#src/helpers/jira/jiraLogWork.js';
|
|
|
8
8
|
import { wrapContent } from '@gaunt-sloth/core/utils/llmUtils.js';
|
|
9
9
|
import { runPrDiscovery } from '#src/commands/prDiscovery.js';
|
|
10
10
|
import { readMultipleFilesFromProjectDir } from '@gaunt-sloth/review/utils/fileUtils.js';
|
|
11
|
+
import { extractChangedPathsFromDiff } from '@gaunt-sloth/review/utils/diffPaths.js';
|
|
12
|
+
import { writeReviewFailureReport } from '@gaunt-sloth/review/modules/reviewFailureReport.js';
|
|
11
13
|
export function prCommand(program, commandLineConfigOverrides) {
|
|
12
14
|
program
|
|
13
15
|
.command('pr')
|
|
@@ -26,16 +28,41 @@ export function prCommand(program, commandLineConfigOverrides) {
|
|
|
26
28
|
const content = [];
|
|
27
29
|
const requirementSource = getEffectiveRequirementSource('pr', config, options.requirementsSource);
|
|
28
30
|
const contentSource = getEffectiveContentSource('pr', config);
|
|
31
|
+
// REL-20 — the label `review()` would have used, hoisted because the failure report has to
|
|
32
|
+
// land at the same path the successful run would have written.
|
|
33
|
+
const reportSource = prId ? `PR-${prId}` : 'PR-discovery';
|
|
34
|
+
/**
|
|
35
|
+
* REL-20 — every exit from this action that happens BEFORE `review()` runs goes through
|
|
36
|
+
* here, so a caller that asked for a report file gets one saying why there is none of the
|
|
37
|
+
* usual content in it. The exit code is unchanged: the run still failed.
|
|
38
|
+
*
|
|
39
|
+
* This is an enumeration of exits, which is exactly the shape that rots by omission — a new
|
|
40
|
+
* guard added below without this call silently reopens the hole for one more input. Anything
|
|
41
|
+
* here that `return`s before the `review()` call must call this first.
|
|
42
|
+
*/
|
|
43
|
+
const failBeforeReview = (message) => {
|
|
44
|
+
displayError(message);
|
|
45
|
+
writeReviewFailureReport(config, reportSource, 'pr', message);
|
|
46
|
+
setExitCode(1);
|
|
47
|
+
};
|
|
29
48
|
if (options.file) {
|
|
30
49
|
content.push(readMultipleFilesFromProjectDir(options.file));
|
|
31
50
|
}
|
|
51
|
+
// CFG-70 — the paths this run's DIFF touches, for `prompts.paths` selection. Declared out
|
|
52
|
+
// here because `gth pr` has TWO content producers, not one: discovery mode's
|
|
53
|
+
// `discoveryResult.diff` and the explicit-PR path's `prContent`. Wiring only the branch one
|
|
54
|
+
// happens to be reading leaves the other silently unscoped.
|
|
55
|
+
//
|
|
56
|
+
// Both take the producer's own output, never `content` — which by then also carries the
|
|
57
|
+
// requirements, `--file` contents and `--message`, any of which may quote a diff for a
|
|
58
|
+
// module this change never touched.
|
|
59
|
+
let changedPaths = [];
|
|
32
60
|
const isDiscovery = !prId && !requirementsId;
|
|
33
61
|
const looksLikeRequirementsOnlyMode = contentSource === 'github' && Boolean(prId) && !requirementsId && !/^\d+$/.test(prId);
|
|
34
62
|
if (looksLikeRequirementsOnlyMode) {
|
|
35
|
-
|
|
63
|
+
failBeforeReview(`Unsupported PR command arguments: "${prId}" was provided as the pull request ID. ` +
|
|
36
64
|
'`gth pr <requirementsId>` requirements-only mode is not supported. ' +
|
|
37
65
|
'Use `gth pr` with no arguments to discover change requirements automatically, or provide both a numeric PR ID and requirements ID: `gth pr <prId> <requirementsId>`.');
|
|
38
|
-
setExitCode(1);
|
|
39
66
|
return;
|
|
40
67
|
}
|
|
41
68
|
// With the GitHub content source, prId ends up interpolated into `gh pr diff <prId>` and
|
|
@@ -43,14 +70,12 @@ export function prCommand(program, commandLineConfigOverrides) {
|
|
|
43
70
|
// depth), but reject garbage upfront with a clear error instead of a downstream warning.
|
|
44
71
|
// Non-GitHub content sources (file/text) accept arbitrary content ids and stay untouched.
|
|
45
72
|
if (contentSource === 'github' && prId && !/^\d+$/.test(prId)) {
|
|
46
|
-
|
|
47
|
-
setExitCode(1);
|
|
73
|
+
failBeforeReview(`Invalid pull request ID "${prId}"; expected a numeric PR number, e.g. \`gth pr 42\`.`);
|
|
48
74
|
return;
|
|
49
75
|
}
|
|
50
76
|
if (isDiscovery) {
|
|
51
77
|
if (config.commands?.pr?.discovery?.enabled === false) {
|
|
52
|
-
|
|
53
|
-
setExitCode(1);
|
|
78
|
+
failBeforeReview('Change requirements discovery is disabled. Provide a pull request ID to run `gth pr`.');
|
|
54
79
|
return;
|
|
55
80
|
}
|
|
56
81
|
try {
|
|
@@ -59,10 +84,10 @@ export function prCommand(program, commandLineConfigOverrides) {
|
|
|
59
84
|
content.push(wrapContent(discoveryResult.requirements, 'discovered-requirements', 'requirements'));
|
|
60
85
|
}
|
|
61
86
|
if (!discoveryResult.diff) {
|
|
62
|
-
|
|
63
|
-
setExitCode(1);
|
|
87
|
+
failBeforeReview('Change requirements discovery did not produce a diff. Cannot continue with review.');
|
|
64
88
|
return;
|
|
65
89
|
}
|
|
90
|
+
changedPaths = extractChangedPathsFromDiff(discoveryResult.diff);
|
|
66
91
|
content.push(wrapContent(discoveryResult.diff, 'discovered-diff', 'GitHub diff'));
|
|
67
92
|
}
|
|
68
93
|
catch (error) {
|
|
@@ -74,11 +99,16 @@ export function prCommand(program, commandLineConfigOverrides) {
|
|
|
74
99
|
for (const row of approvalStopRows(error.parts, { columns: stdout.columns })) {
|
|
75
100
|
displayError(row);
|
|
76
101
|
}
|
|
102
|
+
// REL-20 — the report gets the stop's own message, not the rows above. Those rows are
|
|
103
|
+
// the terminal rendering: a gutter and a wrap computed against this terminal's width,
|
|
104
|
+
// which is meaningless in a file someone posts as a PR comment. The message is already
|
|
105
|
+
// neutralised at construction, so it is safe to write raw.
|
|
106
|
+
writeReviewFailureReport(config, reportSource, 'pr', error.message);
|
|
107
|
+
setExitCode(1);
|
|
77
108
|
}
|
|
78
109
|
else {
|
|
79
|
-
|
|
110
|
+
failBeforeReview(error instanceof Error ? error.message : String(error));
|
|
80
111
|
}
|
|
81
|
-
setExitCode(1);
|
|
82
112
|
return;
|
|
83
113
|
}
|
|
84
114
|
}
|
|
@@ -95,15 +125,14 @@ export function prCommand(program, commandLineConfigOverrides) {
|
|
|
95
125
|
// returns null (with a warning) for an invalid PR number. Without this guard the review
|
|
96
126
|
// would silently proceed against no diff; fail loudly as the throwing path used to.
|
|
97
127
|
if (!prContent) {
|
|
98
|
-
|
|
99
|
-
setExitCode(1);
|
|
128
|
+
failBeforeReview(`Could not retrieve PR content for "${prId}". Cannot continue with review.`);
|
|
100
129
|
return;
|
|
101
130
|
}
|
|
131
|
+
changedPaths = extractChangedPathsFromDiff(prContent);
|
|
102
132
|
content.push(prContent);
|
|
103
133
|
}
|
|
104
134
|
catch (error) {
|
|
105
|
-
|
|
106
|
-
setExitCode(1);
|
|
135
|
+
failBeforeReview(error instanceof Error ? error.message : String(error));
|
|
107
136
|
return;
|
|
108
137
|
}
|
|
109
138
|
}
|
|
@@ -112,11 +141,11 @@ export function prCommand(program, commandLineConfigOverrides) {
|
|
|
112
141
|
}
|
|
113
142
|
const { review } = await import('@gaunt-sloth/review/modules/reviewModule.js');
|
|
114
143
|
const { createResolvers } = await import('@gaunt-sloth/agent/resolvers.js');
|
|
115
|
-
await review(
|
|
144
|
+
await review(reportSource, getReviewSystemPrompt(config), content.join('\n'), config, 'pr', createResolvers(),
|
|
116
145
|
// Bind GitHub-only review tools (gth_gh_read_file) to this PR's repo/ref, so they read
|
|
117
146
|
// the PR under review rather than letting the model guess owner/repo. Undefined prId =
|
|
118
147
|
// discovery mode (current branch's PR), which `gh pr view` resolves on its own.
|
|
119
|
-
{ prId });
|
|
148
|
+
{ prId, changedPaths });
|
|
120
149
|
if (requirementsId &&
|
|
121
150
|
(config.commands?.pr?.requirementSource ?? config.requirementSource) === 'jira' &&
|
|
122
151
|
config.commands?.pr?.logWorkForReviewInSeconds) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prCommand.js","sourceRoot":"","sources":["../../src/commands/prCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,MAAM,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,wCAAwC,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAC;AACnG,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,6BAA6B,EAC7B,qBAAqB,GACtB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAA8B,MAAM,mBAAmB,CAAC;AACrF,OAAO,WAAW,MAAM,kCAAkC,CAAC;AAG3D,OAAO,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9D,OAAO,EAAE,+BAA+B,EAAE,MAAM,wCAAwC,CAAC;
|
|
1
|
+
{"version":3,"file":"prCommand.js","sourceRoot":"","sources":["../../src/commands/prCommand.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import
|
|
1
|
+
import type { GthConfig } from '@gaunt-sloth/core/config.js';
|
|
2
|
+
import type { ProviderConfig } from '@gaunt-sloth/review/sources/types.js';
|
|
3
|
+
import { type RequirementsDiscoveryConfig } from '#src/commands/requirementsDiscovery.js';
|
|
3
4
|
export declare const GSLOTH_PR_DISCOVERY_PROMPT = ".gsloth.pr-discovery.md";
|
|
4
|
-
export interface PrDiscoveryConfig {
|
|
5
|
+
export interface PrDiscoveryConfig extends RequirementsDiscoveryConfig {
|
|
5
6
|
/**
|
|
6
7
|
* Enable change requirements discovery when neither PR id nor requirements id is provided.
|
|
7
8
|
* @default true
|
|
@@ -13,28 +14,6 @@ export interface PrDiscoveryConfig {
|
|
|
13
14
|
* @default true
|
|
14
15
|
*/
|
|
15
16
|
deterministicDiff?: boolean;
|
|
16
|
-
/**
|
|
17
|
-
* Optional tool overrides used only while the discovery agent runs.
|
|
18
|
-
* When omitted, the normal configured tools remain available.
|
|
19
|
-
*/
|
|
20
|
-
filesystem?: string[] | 'all' | 'read' | 'none';
|
|
21
|
-
builtInTools?: BuiltInToolsSetting;
|
|
22
|
-
customTools?: CustomToolsConfig | false;
|
|
23
|
-
tools?: StructuredToolInterface[] | BaseToolkit[] | ServerTool[];
|
|
24
|
-
/**
|
|
25
|
-
* Restrict the discovery agent to this allow-list of tool names, applied after every tool
|
|
26
|
-
* source (filesystem, built-in, custom, MCP, A2A, and `tools`) is resolved. Unlike
|
|
27
|
-
* `builtInTools`/`customTools`/`filesystem` (which gate whole tool groups), this trims the
|
|
28
|
-
* final tool set by exact name, so it can pare down MCP server tools
|
|
29
|
-
* (e.g. "mcp__jira__getJiraIssue") and the discovery helper tools
|
|
30
|
-
* ("gh_pr"/"gh_diff"/"gh_issue"/"set_diff") to the minimum needed.
|
|
31
|
-
*
|
|
32
|
-
* `set_requirements` is always retained regardless, since it is how the discovery agent
|
|
33
|
-
* records the requirements it found. When omitted, all resolved tools remain available; an
|
|
34
|
-
* empty array keeps only `set_requirements`. The discovery agent never inherits the
|
|
35
|
-
* top-level {@link GthConfig.allowedTools}; this property is its only allow-list.
|
|
36
|
-
*/
|
|
37
|
-
allowedTools?: string[];
|
|
38
17
|
}
|
|
39
18
|
declare module '@gaunt-sloth/core/config.js' {
|
|
40
19
|
interface PrCommandConfig {
|
|
@@ -52,3 +31,23 @@ export interface PrDiscoveryResult {
|
|
|
52
31
|
requirements: string;
|
|
53
32
|
}
|
|
54
33
|
export declare function runPrDiscovery(config: GthConfig): Promise<PrDiscoveryResult>;
|
|
34
|
+
export declare function getGithubContentSourceConfig(config: GthConfig): ProviderConfig | null;
|
|
35
|
+
/** Whether a requirement source is one of the Jira sources the deterministic fast path serves. */
|
|
36
|
+
export declare function isJiraRequirementSource(requirementSource: string | undefined): requirementSource is 'jira' | 'jira-legacy';
|
|
37
|
+
/**
|
|
38
|
+
* The Jira half of the deterministic fast path: fetch one issue through the configured Jira
|
|
39
|
+
* requirement source. Returns '' when the issue has no content or the lookup fails, so the caller
|
|
40
|
+
* falls through to the discovery agent.
|
|
41
|
+
*
|
|
42
|
+
* @param foundIn how the key was found, completing "Discovered requirements from Jira issue
|
|
43
|
+
* <key> ..." in the message shown on success.
|
|
44
|
+
*/
|
|
45
|
+
export declare function fetchJiraRequirements(config: GthConfig, requirementSource: 'jira' | 'jira-legacy', issueKey: string, foundIn: string): Promise<string>;
|
|
46
|
+
/**
|
|
47
|
+
* The GitHub half of the deterministic fast path: a GitHub issue the PR description designates
|
|
48
|
+
* as requirements, fetched with `gh issue view`. Returns '' when the description points at none.
|
|
49
|
+
*/
|
|
50
|
+
export declare function discoverGithubIssueRequirementsFromPrMetadata(config: GthConfig, prMetadata: string): Promise<string>;
|
|
51
|
+
export declare function extractGithubPrNumber(prMetadata: string): string | undefined;
|
|
52
|
+
export declare const JIRA_ISSUE_KEY_PATTERN: RegExp;
|
|
53
|
+
export declare function extractJiraIssueKey(prMetadata: string): string | undefined;
|
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { buildSystemMessages, readPromptFile } from '@gaunt-sloth/core/utils/llmUtils.js';
|
|
4
|
-
import { displayTermination } from '@gaunt-sloth/core/core/terminationNotice.js';
|
|
1
|
+
import { displayInfo, displayWarning } from '@gaunt-sloth/core/utils/consoleUtils.js';
|
|
2
|
+
import { readPromptFile } from '@gaunt-sloth/core/utils/llmUtils.js';
|
|
5
3
|
import { debugLog } from '@gaunt-sloth/core/utils/debugUtils.js';
|
|
6
|
-
import { HumanMessage } from '@langchain/core/messages';
|
|
7
|
-
import { MemorySaver } from '@langchain/langgraph';
|
|
8
4
|
import { tool } from '@langchain/core/tools';
|
|
9
5
|
import { z } from 'zod';
|
|
10
6
|
import { dirname, resolve } from 'node:path';
|
|
11
7
|
import { fileURLToPath } from 'node:url';
|
|
12
|
-
import { createResolvers } from '@gaunt-sloth/agent/resolvers.js';
|
|
13
8
|
import { get as getGhPrDiff } from '@gaunt-sloth/review/sources/ghPrDiffSource.js';
|
|
14
9
|
import { get as getGhPrView } from '@gaunt-sloth/review/sources/ghPrViewSource.js';
|
|
15
10
|
import { get as getGhIssue } from '@gaunt-sloth/review/sources/ghIssueSource.js';
|
|
16
11
|
import { get as getJiraIssue } from '@gaunt-sloth/review/sources/jiraIssueSource.js';
|
|
17
12
|
import { get as getJiraIssueLegacy } from '@gaunt-sloth/review/sources/jiraIssueLegacySource.js';
|
|
13
|
+
import { runDiscoveryAgent, } from '#src/commands/requirementsDiscovery.js';
|
|
18
14
|
export const GSLOTH_PR_DISCOVERY_PROMPT = '.gsloth.pr-discovery.md';
|
|
19
15
|
// The assistant package root (src|dist/commands -> package root), where the packaged default
|
|
20
16
|
// .gsloth.pr-discovery.md ships.
|
|
@@ -118,114 +114,19 @@ export async function runPrDiscovery(config) {
|
|
|
118
114
|
!discoveryConfig.allowedTools.includes('set_diff')) {
|
|
119
115
|
displayWarning('No diff yet and commands.pr.discovery.allowedTools excludes both "gh_diff" and "set_diff", so the discovery agent cannot set one. Add "gh_diff" (or "set_diff") to the allow-list, or enable deterministicDiff.');
|
|
120
116
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
// `set_diff`, `set_requirements`, `gh_pr`, `gh_diff`, `gh_issue` — has no built-in access class,
|
|
130
|
-
// so all five are in the rung-independent interrupt set whatever the rung. The first tool call
|
|
131
|
-
// therefore suspends the graph on a LangGraph interrupt, and an interrupt with nowhere to
|
|
132
|
-
// checkpoint throws `MISSING_CHECKPOINTER` instead of suspending — which killed the whole
|
|
133
|
-
// discovery run on its first tool call, before it could set either a diff or requirements.
|
|
134
|
-
//
|
|
135
|
-
// Per run, not per process: this saver's only job is to hold the graph one discovery run
|
|
136
|
-
// suspends on, and that run dies with the runner it is created beside. `MemorySaver` is what
|
|
137
|
-
// every other surface that drives a gating-capable agent hands the runner.
|
|
138
|
-
//
|
|
139
|
-
// GS2-20 — considered for the durable saver and deliberately kept in memory. This is an internal
|
|
140
|
-
// helper run inside `gth pr`, not a conversation the user had; there is nothing here anyone
|
|
141
|
-
// would ask to resume, and persisting it would put rows in the store with no listing entry.
|
|
142
|
-
await runner.init(undefined, getPrDiscoveryAgentConfig(config, discoveryConfig), new MemorySaver(), {
|
|
143
|
-
owningCommand: 'pr',
|
|
144
|
-
});
|
|
145
|
-
await runner.processMessages([
|
|
146
|
-
...buildSystemMessages(config, readPrDiscoveryPrompt(config)),
|
|
147
|
-
new HumanMessage(buildPrDiscoveryUserMessage(state)),
|
|
148
|
-
]);
|
|
149
|
-
}
|
|
150
|
-
finally {
|
|
151
|
-
await runner.cleanup();
|
|
152
|
-
// [[EXT-159]] — say why the DISCOVERY run ended, because on the ending that matters nobody
|
|
153
|
-
// else will.
|
|
154
|
-
//
|
|
155
|
-
// Several endings return from `processMessages` normally rather than throwing — the interrupt
|
|
156
|
-
// drain giving up, the tool-error budget and the tool-loop guard ending the graph with
|
|
157
|
-
// `jumpTo: 'end'`, an Esc or abort closing the stream, a tool exception returned as the turn's
|
|
158
|
-
// answer, and a refusal or truncation classified from the provider's own metadata. Each leaves
|
|
159
|
-
// `state.diff` unset, and `prCommand` then prints "Change requirements discovery did not
|
|
160
|
-
// produce a diff" and RETURNS — so `review`'s own notice, the surface this run's ending used to
|
|
161
|
-
// be attributed to, is never reached. One sentence that fits a dozen unrelated causes, printed
|
|
162
|
-
// while the discriminating fact sat unread on this runner: the exact shape this node exists to
|
|
163
|
-
// remove.
|
|
164
|
-
//
|
|
165
|
-
// In the `finally`, so the endings that DO throw are announced too. Note the ORDER that buys:
|
|
166
|
-
// the `finally` unwinds ahead of `prCommand`'s catch, so the notice prints FIRST and the
|
|
167
|
-
// provider's prose (or the approvals negotiation transcript) follows it — a heading, then the
|
|
168
|
-
// detail, rather than `reviewModule`'s error-then-notice.
|
|
169
|
-
//
|
|
170
|
-
// A successful discovery costs nothing: it classifies `completed`, which
|
|
171
|
-
// `shouldAnnounceTermination` suppresses, so the review that follows is not preceded by a
|
|
172
|
-
// notice about the sub-run that fed it. The one case that does print twice is a discovery that
|
|
173
|
-
// ended abnormally AFTER the agent had already set a diff — `prCommand` then continues to the
|
|
174
|
-
// review, and the user sees this notice and later the review's own. That is two runs with two
|
|
175
|
-
// different endings, each stating its own, which is the intended reading rather than a
|
|
176
|
-
// duplicate.
|
|
177
|
-
//
|
|
178
|
-
// Read after `cleanup()` for the reason `reviewModule` reads it there: the agent is gone by
|
|
179
|
-
// here and the runner snapshots its innermost classification at cleanup.
|
|
180
|
-
try {
|
|
181
|
-
displayTermination(runner.getTerminationReason());
|
|
182
|
-
}
|
|
183
|
-
catch {
|
|
184
|
-
/* fail-soft: explaining a run must never be what ends it */
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
// The discovery agent streams its final text without a trailing newline, so emit a
|
|
188
|
-
// blank line to separate it from the review agent's output that follows.
|
|
189
|
-
displayInfo('');
|
|
117
|
+
await runDiscoveryAgent({
|
|
118
|
+
config,
|
|
119
|
+
discoveryConfig,
|
|
120
|
+
owningCommand: 'pr',
|
|
121
|
+
readPrompt: () => readPrDiscoveryPrompt(config),
|
|
122
|
+
userMessage: buildPrDiscoveryUserMessage(state),
|
|
123
|
+
createDiscoveryTools: () => createPrDiscoveryTools(config, state),
|
|
124
|
+
});
|
|
190
125
|
return {
|
|
191
126
|
diff: state.diff.trim(),
|
|
192
127
|
requirements: state.requirements.trim(),
|
|
193
128
|
};
|
|
194
129
|
}
|
|
195
|
-
function getPrDiscoveryAgentConfig(config, discoveryConfig) {
|
|
196
|
-
const baseTools = discoveryConfig?.tools ?? config.tools ?? [];
|
|
197
|
-
const customTools = discoveryConfig && 'customTools' in discoveryConfig
|
|
198
|
-
? discoveryConfig.customTools
|
|
199
|
-
: config.customTools;
|
|
200
|
-
return {
|
|
201
|
-
...config,
|
|
202
|
-
filesystem: discoveryConfig?.filesystem ?? config.filesystem,
|
|
203
|
-
builtInTools: discoveryConfig?.builtInTools ?? config.builtInTools,
|
|
204
|
-
customTools: customTools === false ? undefined : customTools,
|
|
205
|
-
tools: baseTools,
|
|
206
|
-
// The discovery agent must never inherit the top-level allow-list (e.g. a global
|
|
207
|
-
// `allowedTools: []` meant to keep review agents tool-free would strip set_requirements
|
|
208
|
-
// and silently neuter discovery). Only `commands.pr.discovery.allowedTools` applies here,
|
|
209
|
-
// always augmented with set_requirements so the agent can record what it found. The
|
|
210
|
-
// agent applies this list after every tool source is resolved, so it also gates tools
|
|
211
|
-
// supplied via `tools` in config.
|
|
212
|
-
allowedTools: discoveryConfig?.allowedTools
|
|
213
|
-
? [...new Set([...discoveryConfig.allowedTools, 'set_requirements'])]
|
|
214
|
-
: undefined,
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
function createPrDiscoveryResolvers(config, state) {
|
|
218
|
-
const baseResolvers = createResolvers();
|
|
219
|
-
return {
|
|
220
|
-
...baseResolvers,
|
|
221
|
-
resolveTools: async (effectiveConfig, command) => {
|
|
222
|
-
const baseTools = baseResolvers.resolveTools
|
|
223
|
-
? await baseResolvers.resolveTools(effectiveConfig, command)
|
|
224
|
-
: [];
|
|
225
|
-
return [...baseTools, ...createPrDiscoveryTools(config, state)];
|
|
226
|
-
},
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
130
|
function createPrDiscoveryTools(config, state) {
|
|
230
131
|
const setDiff = tool(async ({ diff }) => {
|
|
231
132
|
state.diff = diff;
|
|
@@ -304,7 +205,7 @@ function createPrDiscoveryTools(config, state) {
|
|
|
304
205
|
function getSourceConfig(config) {
|
|
305
206
|
return config && typeof config === 'object' ? config : null;
|
|
306
207
|
}
|
|
307
|
-
function getGithubContentSourceConfig(config) {
|
|
208
|
+
export function getGithubContentSourceConfig(config) {
|
|
308
209
|
return getSourceConfig(config.contentSourceConfig?.github);
|
|
309
210
|
}
|
|
310
211
|
function getGithubRequirementSourceConfig(config) {
|
|
@@ -317,6 +218,10 @@ function getJiraRequirementSourceConfig(config) {
|
|
|
317
218
|
// path uses the built-in config - keep them in sync to avoid surprises.
|
|
318
219
|
return getSourceConfig(config.builtInToolsConfig?.jira ?? config.requirementSourceConfig?.jira);
|
|
319
220
|
}
|
|
221
|
+
/** Whether a requirement source is one of the Jira sources the deterministic fast path serves. */
|
|
222
|
+
export function isJiraRequirementSource(requirementSource) {
|
|
223
|
+
return requirementSource === 'jira' || requirementSource === 'jira-legacy';
|
|
224
|
+
}
|
|
320
225
|
/**
|
|
321
226
|
* Deterministically resolve requirements from PR metadata, using a fast path that matches
|
|
322
227
|
* the configured requirement source. Falls back to '' when nothing is found, leaving the
|
|
@@ -324,30 +229,48 @@ function getJiraRequirementSourceConfig(config) {
|
|
|
324
229
|
*/
|
|
325
230
|
async function discoverRequirementsFromPrMetadata(config, prMetadata) {
|
|
326
231
|
const requirementSource = config.commands?.pr?.requirementSource ?? config.requirementSource;
|
|
327
|
-
if (requirementSource
|
|
232
|
+
if (isJiraRequirementSource(requirementSource)) {
|
|
328
233
|
const issueKey = extractJiraIssueKey(prMetadata);
|
|
329
234
|
if (!issueKey) {
|
|
330
235
|
return '';
|
|
331
236
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
237
|
+
return fetchJiraRequirements(config, requirementSource, issueKey, 'linked in the PR description');
|
|
238
|
+
}
|
|
239
|
+
return discoverGithubIssueRequirementsFromPrMetadata(config, prMetadata);
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* The Jira half of the deterministic fast path: fetch one issue through the configured Jira
|
|
243
|
+
* requirement source. Returns '' when the issue has no content or the lookup fails, so the caller
|
|
244
|
+
* falls through to the discovery agent.
|
|
245
|
+
*
|
|
246
|
+
* @param foundIn how the key was found, completing "Discovered requirements from Jira issue
|
|
247
|
+
* <key> ..." in the message shown on success.
|
|
248
|
+
*/
|
|
249
|
+
export async function fetchJiraRequirements(config, requirementSource, issueKey, foundIn) {
|
|
250
|
+
const jiraConfig = getJiraRequirementSourceConfig(config);
|
|
251
|
+
try {
|
|
252
|
+
const requirements = (requirementSource === 'jira-legacy'
|
|
253
|
+
? await getJiraIssueLegacy(jiraConfig, issueKey)
|
|
254
|
+
: await getJiraIssue(jiraConfig, issueKey)) ?? '';
|
|
255
|
+
if (requirements) {
|
|
256
|
+
displayInfo(`Discovered requirements from Jira issue ${issueKey} ${foundIn}.`);
|
|
349
257
|
}
|
|
258
|
+
return requirements;
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
// The deterministic Jira fast path uses the Jira REST API, which needs its own
|
|
262
|
+
// credentials (PAT / base64 token) that are independent of any Jira MCP OAuth. When
|
|
263
|
+
// those aren't configured - e.g. an MCP-only setup - skip quietly and let the discovery
|
|
264
|
+
// agent resolve requirements via its tools (e.g. the Jira MCP server).
|
|
265
|
+
debugLog(`Skipped the deterministic Jira REST lookup for ${issueKey}: ${error instanceof Error ? error.message : String(error)}`);
|
|
266
|
+
return '';
|
|
350
267
|
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* The GitHub half of the deterministic fast path: a GitHub issue the PR description designates
|
|
271
|
+
* as requirements, fetched with `gh issue view`. Returns '' when the description points at none.
|
|
272
|
+
*/
|
|
273
|
+
export async function discoverGithubIssueRequirementsFromPrMetadata(config, prMetadata) {
|
|
351
274
|
const requirementsIssueRef = extractRequirementsGithubIssueRef(prMetadata);
|
|
352
275
|
if (!requirementsIssueRef) {
|
|
353
276
|
return '';
|
|
@@ -440,7 +363,7 @@ function normalizeGithubIssueUrl(url) {
|
|
|
440
363
|
function formatGithubIssueRef(ref) {
|
|
441
364
|
return /^\d+$/.test(ref) ? `#${ref}` : ref;
|
|
442
365
|
}
|
|
443
|
-
function extractGithubPrNumber(prMetadata) {
|
|
366
|
+
export function extractGithubPrNumber(prMetadata) {
|
|
444
367
|
// formatPrView emits "GitHub PR: #<number>" as the first line when the number is known. Anchor
|
|
445
368
|
// to that first line so a PR body that merely contains the literal "GitHub PR: #123" cannot
|
|
446
369
|
// spoof the number shown in the info message.
|
|
@@ -449,12 +372,12 @@ function extractGithubPrNumber(prMetadata) {
|
|
|
449
372
|
// Jira project keys are at least two letters followed by letters/digits (e.g. ABC-123,
|
|
450
373
|
// never A-1). Kept case-sensitive for bare keys: lowercase look-alikes in branch names or
|
|
451
374
|
// prose ("fix-123") are too ambiguous for the deterministic path.
|
|
452
|
-
const JIRA_ISSUE_KEY_PATTERN = /\b([A-Z]{2}[A-Z0-9]*-\d+)\b/;
|
|
375
|
+
export const JIRA_ISSUE_KEY_PATTERN = /\b([A-Z]{2}[A-Z0-9]*-\d+)\b/;
|
|
453
376
|
// Atlassian browse URL, e.g. https://company.atlassian.net/browse/ABC-123. Unlike bare keys,
|
|
454
377
|
// URL-extracted keys are matched case-insensitively and normalized because the structured
|
|
455
378
|
// /browse/<key> path makes the intent clear while copied URLs can vary in casing.
|
|
456
379
|
const ATLASSIAN_BROWSE_URL_PATTERN = /atlassian\.net\/browse\/([A-Z]{2}[A-Z0-9]*-\d+)/i;
|
|
457
|
-
function extractJiraIssueKey(prMetadata) {
|
|
380
|
+
export function extractJiraIssueKey(prMetadata) {
|
|
458
381
|
const requirementsLine = getPrDescriptionBody(prMetadata)
|
|
459
382
|
.split('\n')
|
|
460
383
|
.find((line) => REQUIREMENTS_LABEL_PATTERN.test(line));
|