ghostrail 0.16.0 → 0.17.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/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +106 -16
- package/dist/cli/commands.js.map +1 -1
- package/dist/commands/help.d.ts.map +1 -1
- package/dist/commands/help.js +4 -3
- package/dist/commands/help.js.map +1 -1
- package/dist/factory/build.d.ts.map +1 -1
- package/dist/factory/build.js +1 -0
- package/dist/factory/build.js.map +1 -1
- package/dist/init/regions.d.ts +76 -0
- package/dist/init/regions.d.ts.map +1 -0
- package/dist/init/regions.js +247 -0
- package/dist/init/regions.js.map +1 -0
- package/dist/init/template.d.ts +7 -1
- package/dist/init/template.d.ts.map +1 -1
- package/dist/init/template.js +37 -2
- package/dist/init/template.js.map +1 -1
- package/dist/publish/gh.d.ts +8 -0
- package/dist/publish/gh.d.ts.map +1 -1
- package/dist/publish/gh.js +12 -0
- package/dist/publish/gh.js.map +1 -1
- package/dist/publish/githost.d.ts +8 -0
- package/dist/publish/githost.d.ts.map +1 -1
- package/dist/publish/githost.js.map +1 -1
- package/dist/publish/index.d.ts +1 -1
- package/dist/publish/index.d.ts.map +1 -1
- package/dist/publish/index.js +1 -1
- package/dist/publish/index.js.map +1 -1
- package/dist/respond/index.d.ts +3 -2
- package/dist/respond/index.d.ts.map +1 -1
- package/dist/respond/index.js +3 -2
- package/dist/respond/index.js.map +1 -1
- package/dist/respond/merge.d.ts +13 -0
- package/dist/respond/merge.d.ts.map +1 -0
- package/dist/respond/merge.js +181 -0
- package/dist/respond/merge.js.map +1 -0
- package/dist/respond/respond.d.ts +25 -5
- package/dist/respond/respond.d.ts.map +1 -1
- package/dist/respond/respond.js +57 -28
- package/dist/respond/respond.js.map +1 -1
- package/dist/respond/select.d.ts +15 -0
- package/dist/respond/select.d.ts.map +1 -1
- package/dist/respond/select.js +17 -0
- package/dist/respond/select.js.map +1 -1
- package/package.json +1 -1
- package/skill/ghostrail/SKILL.md +80 -10
- package/templates/code/prompts/resolve-issue.md +13 -4
- package/templates/code/prompts/respond.md +4 -0
- package/templates/code/prompts/triage.md +6 -0
- package/templates/content/prompts/draft.md +6 -0
- package/templates/content/prompts/respond.md +4 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"githost.js","sourceRoot":"","sources":["../../src/publish/githost.ts"],"names":[],"mappings":"AAEA,4FAA4F;AAC5F,MAAM,CAAC,MAAM,gBAAgB,GAAG,oBAAoB,CAAC;AAErD;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,YAAY,CAAC;AAExC;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO;QACL,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACxB,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC;KACnC,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,OAAO,CACL,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC;QAChC,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC;QAChC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC;QAC3B,wBAAwB,CAAC,IAAI,CAAC,MAAM,CAAC,CACtC,CAAC;AACJ,CAAC;
|
|
1
|
+
{"version":3,"file":"githost.js","sourceRoot":"","sources":["../../src/publish/githost.ts"],"names":[],"mappings":"AAEA,4FAA4F;AAC5F,MAAM,CAAC,MAAM,gBAAgB,GAAG,oBAAoB,CAAC;AAErD;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,YAAY,CAAC;AAExC;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO;QACL,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACxB,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC;KACnC,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,OAAO,CACL,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC;QAChC,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC;QAChC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC;QAC3B,wBAAwB,CAAC,IAAI,CAAC,MAAM,CAAC,CACtC,CAAC;AACJ,CAAC;AAwED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAC1D,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,sCAAsC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AACrD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,EAAU,EAAE,KAAa,EAAE,IAAI,GAAG,KAAK;IACnE,OAAO,GAAG,IAAI,KAAK,KAAK,KAAK,EAAE,GAAG,CAAC;AACrC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,MAAM,CAAC,IAAc,EAAE,OAAe,EAAE,QAAiB;IACvE,MAAM,KAAK,GAAG,CAAC,iBAAiB,EAAE,EAAE,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAEtD,2EAA2E;IAC3E,MAAM,IAAI,GAAG,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC9B,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1C,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED,yEAAyE;IACzE,kEAAkE;IAClE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,mBAAmB,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;IACzD,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;IACjC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
package/dist/publish/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { GhHost, type GhRunner, ghOpenPrArgs, parseCommentList, parseOpenPrList, parsePrStatus, } from "./gh.js";
|
|
1
|
+
export { GhHost, type GhRunner, ghMergePrArgs, ghOpenPrArgs, parseCommentList, parseOpenPrList, parsePrStatus, } from "./gh.js";
|
|
2
2
|
export { type CheckRun, type GitHost, GHOSTRAIL_MARKER, commitMessage, type OpenPr, type PrComment, type PrRef, type PrSpec, type PrStatus, parsePrUrl, prBody, } from "./githost.js";
|
|
3
3
|
export { GitHubPublisher, type PublisherOptions } from "./github-publisher.js";
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/publish/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,KAAK,QAAQ,EACb,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,OAAO,EACZ,gBAAgB,EAChB,aAAa,EACb,KAAK,MAAM,EACX,KAAK,SAAS,EACd,KAAK,KAAK,EACV,KAAK,MAAM,EACX,KAAK,QAAQ,EACb,UAAU,EACV,MAAM,GACP,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/publish/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,KAAK,QAAQ,EACb,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,OAAO,EACZ,gBAAgB,EAChB,aAAa,EACb,KAAK,MAAM,EACX,KAAK,SAAS,EACd,KAAK,KAAK,EACV,KAAK,MAAM,EACX,KAAK,QAAQ,EACb,UAAU,EACV,MAAM,GACP,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
|
package/dist/publish/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { GhHost, ghOpenPrArgs, parseCommentList, parseOpenPrList, parsePrStatus, } from "./gh.js";
|
|
1
|
+
export { GhHost, ghMergePrArgs, ghOpenPrArgs, parseCommentList, parseOpenPrList, parsePrStatus, } from "./gh.js";
|
|
2
2
|
export { GHOSTRAIL_MARKER, commitMessage, parsePrUrl, prBody, } from "./githost.js";
|
|
3
3
|
export { GitHubPublisher } from "./github-publisher.js";
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/publish/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EAEN,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAGL,gBAAgB,EAChB,aAAa,EAMb,UAAU,EACV,MAAM,GACP,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAyB,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/publish/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EAEN,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAGL,gBAAgB,EAChB,aAAa,EAMb,UAAU,EACV,MAAM,GACP,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAyB,MAAM,uBAAuB,CAAC"}
|
package/dist/respond/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { FEEDBACK_PATH, type RespondConfig, type RespondDeps, type RespondResult, type RespondState, renderFeedback, respondTick, } from "./respond.js";
|
|
2
|
-
export {
|
|
1
|
+
export { FEEDBACK_PATH, commitAndPush, markedComment, type RespondConfig, type RespondDeps, type RespondResult, type RespondState, renderFeedback, respondTick, } from "./respond.js";
|
|
2
|
+
export { parseUnmergedPaths, renderConflictInstruction, resolveConflictsAndMergeSafely, } from "./merge.js";
|
|
3
|
+
export { MERGE_COMMAND_PHRASE, isMergeCommand, latestTimestamp, type SelectOptions, selectNewComments, } from "./select.js";
|
|
3
4
|
export { FileWatermarkStore, MemoryWatermarkStore, type WatermarkStore } from "./store.js";
|
|
4
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/respond/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,cAAc,EACd,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/respond/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,aAAa,EACb,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,cAAc,EACd,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,eAAe,EACf,KAAK,aAAa,EAClB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/respond/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { FEEDBACK_PATH, renderFeedback, respondTick, } from "./respond.js";
|
|
2
|
-
export {
|
|
1
|
+
export { FEEDBACK_PATH, commitAndPush, markedComment, renderFeedback, respondTick, } from "./respond.js";
|
|
2
|
+
export { parseUnmergedPaths, renderConflictInstruction, resolveConflictsAndMergeSafely, } from "./merge.js";
|
|
3
|
+
export { MERGE_COMMAND_PHRASE, isMergeCommand, latestTimestamp, selectNewComments, } from "./select.js";
|
|
3
4
|
export { FileWatermarkStore, MemoryWatermarkStore } from "./store.js";
|
|
4
5
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/respond/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAKb,cAAc,EACd,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/respond/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,aAAa,EACb,aAAa,EAKb,cAAc,EACd,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,eAAe,EAEf,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAuB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Logger } from "../loop/ports.js";
|
|
2
|
+
import type { OpenPr, PrComment } from "../publish/githost.js";
|
|
3
|
+
import { type RespondConfig, type RespondDeps, type RespondResult } from "./respond.js";
|
|
4
|
+
/**
|
|
5
|
+
* Parse `git diff --name-only --diff-filter=U` output into the paths still
|
|
6
|
+
* carrying unresolved conflict markers, one per line, blank lines dropped.
|
|
7
|
+
*/
|
|
8
|
+
export declare function parseUnmergedPaths(stdout: string): string[];
|
|
9
|
+
/** The instruction the agent gets in place of human feedback: resolve the merge, nothing else. */
|
|
10
|
+
export declare function renderConflictInstruction(baseBranch: string, files: readonly string[]): string;
|
|
11
|
+
/** `resolveConflictsAndMerge`, guaranteed not to throw (see `respondToPrSafely`'s reasoning). */
|
|
12
|
+
export declare function resolveConflictsAndMergeSafely(deps: RespondDeps, config: RespondConfig, pr: OpenPr, fresh: readonly PrComment[], logger: Logger): Promise<RespondResult>;
|
|
13
|
+
//# sourceMappingURL=merge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/respond/merge.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAgB,MAAM,EAAY,MAAM,kBAAkB,CAAC;AACvE,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,EAGnB,MAAM,cAAc,CAAC;AAGtB;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAK3D;AAED,kGAAkG;AAClG,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAa9F;AAiFD,iGAAiG;AACjG,wBAAsB,8BAA8B,CAClD,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,aAAa,EACrB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,aAAa,CAAC,CAQxB"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { writeWorkspaceFile } from "../backend/fs.js";
|
|
2
|
+
import { FEEDBACK_PATH, commitAndPush, markedComment, } from "./respond.js";
|
|
3
|
+
import { latestTimestamp } from "./select.js";
|
|
4
|
+
/**
|
|
5
|
+
* Parse `git diff --name-only --diff-filter=U` output into the paths still
|
|
6
|
+
* carrying unresolved conflict markers, one per line, blank lines dropped.
|
|
7
|
+
*/
|
|
8
|
+
export function parseUnmergedPaths(stdout) {
|
|
9
|
+
return stdout
|
|
10
|
+
.split("\n")
|
|
11
|
+
.map((line) => line.trim())
|
|
12
|
+
.filter((line) => line.length > 0);
|
|
13
|
+
}
|
|
14
|
+
/** The instruction the agent gets in place of human feedback: resolve the merge, nothing else. */
|
|
15
|
+
export function renderConflictInstruction(baseBranch, files) {
|
|
16
|
+
const list = files.map((file) => `- ${file}`).join("\n");
|
|
17
|
+
return [
|
|
18
|
+
"# Resolve merge conflicts",
|
|
19
|
+
"",
|
|
20
|
+
`Merging \`${baseBranch}\` into this branch left conflict markers in:`,
|
|
21
|
+
"",
|
|
22
|
+
list,
|
|
23
|
+
"",
|
|
24
|
+
"Resolve every conflict so the result is correct and consistent with both",
|
|
25
|
+
"sides' intent, then stage the resolution. Do not address anything else —",
|
|
26
|
+
"no other feedback, no unrelated cleanup.",
|
|
27
|
+
].join("\n");
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Fetch `baseBranch` and merge it into the workspace's current branch.
|
|
31
|
+
* Distinguishes a real conflict (unresolved paths after a failed merge) from
|
|
32
|
+
* any other merge failure, which is thrown rather than silently treated as a
|
|
33
|
+
* conflict with nothing to resolve.
|
|
34
|
+
*/
|
|
35
|
+
async function mergeBaseIntoBranch(backend, workspace, baseBranch) {
|
|
36
|
+
const fetch = await backend.exec(workspace, ["git", "fetch", "origin", baseBranch]);
|
|
37
|
+
if (fetch.exitCode !== 0) {
|
|
38
|
+
throw new Error(`git fetch origin ${baseBranch} failed: ${fetch.stderr.trim() || fetch.stdout.trim()}`);
|
|
39
|
+
}
|
|
40
|
+
const before = await backend.exec(workspace, ["git", "rev-parse", "HEAD"]);
|
|
41
|
+
const merge = await backend.exec(workspace, [
|
|
42
|
+
"git",
|
|
43
|
+
"merge",
|
|
44
|
+
`origin/${baseBranch}`,
|
|
45
|
+
"--no-edit",
|
|
46
|
+
]);
|
|
47
|
+
if (merge.exitCode === 0) {
|
|
48
|
+
const after = await backend.exec(workspace, ["git", "rev-parse", "HEAD"]);
|
|
49
|
+
return { status: before.stdout.trim() === after.stdout.trim() ? "up-to-date" : "merged" };
|
|
50
|
+
}
|
|
51
|
+
const unmerged = await backend.exec(workspace, ["git", "diff", "--name-only", "--diff-filter=U"]);
|
|
52
|
+
const files = parseUnmergedPaths(unmerged.stdout);
|
|
53
|
+
if (files.length === 0) {
|
|
54
|
+
throw new Error(`git merge origin/${baseBranch} failed: ${merge.stderr.trim() || merge.stdout.trim()}`);
|
|
55
|
+
}
|
|
56
|
+
return { status: "conflict", files };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Ask the configured agent to resolve the conflicted files left by
|
|
60
|
+
* {@link mergeBaseIntoBranch}, using the same agent/guardrails the ordinary
|
|
61
|
+
* respond flow uses for feedback, but with a dedicated instruction in place
|
|
62
|
+
* of the human's comment.
|
|
63
|
+
*/
|
|
64
|
+
async function resolveWithAgent(deps, config, pr, workspace, baseBranch, files) {
|
|
65
|
+
await writeWorkspaceFile(deps.backend, workspace, FEEDBACK_PATH, renderConflictInstruction(baseBranch, files));
|
|
66
|
+
const item = {
|
|
67
|
+
id: `PR-${pr.number}-merge`,
|
|
68
|
+
title: `resolve conflicts with ${baseBranch} for PR #${pr.number}`,
|
|
69
|
+
url: pr.url,
|
|
70
|
+
};
|
|
71
|
+
return deps.agent.run({
|
|
72
|
+
backend: deps.backend,
|
|
73
|
+
workspace,
|
|
74
|
+
item,
|
|
75
|
+
agent: config.agent,
|
|
76
|
+
guardrails: config.guardrails,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/** `resolveConflictsAndMerge`, guaranteed not to throw (see `respondToPrSafely`'s reasoning). */
|
|
80
|
+
export async function resolveConflictsAndMergeSafely(deps, config, pr, fresh, logger) {
|
|
81
|
+
try {
|
|
82
|
+
return await resolveConflictsAndMerge(deps, config, pr, fresh, logger);
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
86
|
+
logger.warn(`merge #${pr.number}: ${message}`);
|
|
87
|
+
return { prNumber: pr.number, state: "failed", summary: message };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async function resolveConflictsAndMerge(deps, config, pr, fresh, logger) {
|
|
91
|
+
let workspace;
|
|
92
|
+
try {
|
|
93
|
+
workspace = await deps.backend.provision({
|
|
94
|
+
repoPath: deps.repoPath,
|
|
95
|
+
baseBranch: pr.headBranch,
|
|
96
|
+
branch: pr.headBranch,
|
|
97
|
+
mode: "attach",
|
|
98
|
+
...(deps.claudeProfileDir === undefined ? {} : { profileDir: deps.claudeProfileDir }),
|
|
99
|
+
});
|
|
100
|
+
const result = await runMerge(deps, config, pr, workspace, logger);
|
|
101
|
+
const mark = latestTimestamp(fresh);
|
|
102
|
+
if (mark !== undefined)
|
|
103
|
+
await deps.watermarks.set(pr.number, mark);
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
108
|
+
logger.warn(`merge #${pr.number}: errored: ${message}`);
|
|
109
|
+
return { prNumber: pr.number, state: "failed", summary: message };
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
if (workspace !== undefined) {
|
|
113
|
+
try {
|
|
114
|
+
await deps.backend.teardown(workspace);
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// best-effort
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
async function runMerge(deps, config, pr, workspace, logger) {
|
|
123
|
+
const merge = await mergeBaseIntoBranch(deps.backend, workspace, deps.baseBranch);
|
|
124
|
+
if (merge.status === "conflict") {
|
|
125
|
+
const outcome = await resolveWithAgent(deps, config, pr, workspace, deps.baseBranch, merge.files);
|
|
126
|
+
if (outcome.status !== "done") {
|
|
127
|
+
return postUnresolved(deps, pr, deps.baseBranch, outcome);
|
|
128
|
+
}
|
|
129
|
+
const committed = await commitAndPush(deps.backend, workspace, `merge: resolve conflicts with ${deps.baseBranch}`);
|
|
130
|
+
if (!committed) {
|
|
131
|
+
const body = `Could not resolve the conflicts with \`${deps.baseBranch}\`: the agent made no changes.`;
|
|
132
|
+
await deps.host.postComment(pr.number, markedComment(body));
|
|
133
|
+
return { prNumber: pr.number, state: "failed", summary: body };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else if (merge.status === "merged") {
|
|
137
|
+
const push = await deps.backend.exec(workspace, ["git", "push", "origin", workspace.branch]);
|
|
138
|
+
if (push.exitCode !== 0) {
|
|
139
|
+
throw new Error(`git push failed: ${push.stderr.trim() || push.stdout.trim()}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
await deps.host.mergePr(pr.number);
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
// The branch itself is already in the state this feature promises (conflicts
|
|
147
|
+
// resolved and pushed, or already current); only the final `gh pr merge` call
|
|
148
|
+
// failed, e.g. a required check that has not finished. That real progress
|
|
149
|
+
// belongs in the comment, not a silent "failed" with nothing to show for it.
|
|
150
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
151
|
+
const body = merge.status === "conflict"
|
|
152
|
+
? `Resolved conflicts with \`${deps.baseBranch}\` and pushed, but merging the PR failed: ${message}`
|
|
153
|
+
: `The branch is up to date with \`${deps.baseBranch}\`, but merging the PR failed: ${message}`;
|
|
154
|
+
await deps.host.postComment(pr.number, markedComment(body));
|
|
155
|
+
return { prNumber: pr.number, state: "failed", summary: message };
|
|
156
|
+
}
|
|
157
|
+
const body = merge.status === "conflict"
|
|
158
|
+
? `Resolved conflicts with \`${deps.baseBranch}\` and merged.`
|
|
159
|
+
: `Merged into \`${deps.baseBranch}\`.`;
|
|
160
|
+
await deps.host.postComment(pr.number, markedComment(body));
|
|
161
|
+
logger.info(`merge #${pr.number}: merged`);
|
|
162
|
+
return { prNumber: pr.number, state: "responded", summary: body };
|
|
163
|
+
}
|
|
164
|
+
/** Post why conflict resolution stopped short of a merge, for every non-`done` agent outcome. */
|
|
165
|
+
async function postUnresolved(deps, pr, baseBranch, outcome) {
|
|
166
|
+
if (outcome.status === "blocked") {
|
|
167
|
+
const body = `Could not resolve the conflicts with \`${baseBranch}\` automatically:\n\n${outcome.questions}`;
|
|
168
|
+
await deps.host.postComment(pr.number, markedComment(body));
|
|
169
|
+
return { prNumber: pr.number, state: "blocked", summary: outcome.questions };
|
|
170
|
+
}
|
|
171
|
+
if (outcome.status === "failed") {
|
|
172
|
+
const body = `The factory hit an error resolving conflicts with \`${baseBranch}\`: ${outcome.error}`;
|
|
173
|
+
await deps.host.postComment(pr.number, markedComment(body));
|
|
174
|
+
return { prNumber: pr.number, state: "failed", summary: outcome.error };
|
|
175
|
+
}
|
|
176
|
+
const reason = outcome.reason ?? "the agent made no changes";
|
|
177
|
+
const body = `Could not resolve the conflicts with \`${baseBranch}\`: ${reason}.`;
|
|
178
|
+
await deps.host.postComment(pr.number, markedComment(body));
|
|
179
|
+
return { prNumber: pr.number, state: "failed", summary: reason };
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=merge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/respond/merge.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Backend } from "../backend/types.js";
|
|
1
|
+
import type { Backend, Workspace } from "../backend/types.js";
|
|
2
2
|
import type { AgentConfig, Guardrails } from "../config/schema.js";
|
|
3
3
|
import type { Agent, Logger, Source } from "../loop/ports.js";
|
|
4
4
|
import { type GitHost, type PrComment } from "../publish/githost.js";
|
|
@@ -11,6 +11,12 @@ export interface RespondDeps {
|
|
|
11
11
|
backend: Backend;
|
|
12
12
|
agent: Agent;
|
|
13
13
|
watermarks: WatermarkStore;
|
|
14
|
+
/**
|
|
15
|
+
* The factory's base branch, e.g. "main". Only consulted by the
|
|
16
|
+
* resolve-conflicts-and-merge flow, to know what to merge into a PR branch
|
|
17
|
+
* before merging the PR itself.
|
|
18
|
+
*/
|
|
19
|
+
baseBranch: string;
|
|
14
20
|
/** Optional tracker source; when set, the respond pass also folds in new
|
|
15
21
|
* tracker (e.g. Linear) comments on the PR's issue, not just PR comments. */
|
|
16
22
|
source?: Source;
|
|
@@ -41,13 +47,27 @@ export interface RespondResult {
|
|
|
41
47
|
}
|
|
42
48
|
/** Render fresh human comments into the feedback document the agent reads. */
|
|
43
49
|
export declare function renderFeedback(comments: readonly PrComment[]): string;
|
|
50
|
+
/** Comment body ghostrail posts, always carrying the marker so it never re-reads its own. */
|
|
51
|
+
export declare function markedComment(body: string): string;
|
|
44
52
|
/**
|
|
45
53
|
* The respond pass: for every open factory PR, act only on human comments newer
|
|
46
54
|
* than the per-PR watermark that do not carry the ghostrail marker (so it never
|
|
47
|
-
* acts on its own).
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
55
|
+
* acts on its own). A PR whose fresh comments ask the factory to resolve
|
|
56
|
+
* conflicts and merge (see {@link isMergeCommand}) is routed to that flow
|
|
57
|
+
* instead of the ordinary one; every other PR gets its new feedback handed to
|
|
58
|
+
* the agent, and — on a successful change — committed, pushed to the same
|
|
59
|
+
* branch, and summarized in a comment. The ordinary flow never opens a new PR
|
|
60
|
+
* and never merges. The watermark advances once a PR's new comments have been
|
|
61
|
+
* handled, on every path (success, blocked, or failed).
|
|
51
62
|
*/
|
|
52
63
|
export declare function respondTick(deps: RespondDeps, config: RespondConfig): Promise<RespondResult[]>;
|
|
64
|
+
/**
|
|
65
|
+
* Commit (with `message`) and push the workspace's changes to its branch.
|
|
66
|
+
* Returns false if there was nothing to commit. Shared with the
|
|
67
|
+
* resolve-conflicts-and-merge flow, where `message` names the merge rather
|
|
68
|
+
* than the feedback that prompted it, and a conflicted merge's resolution is
|
|
69
|
+
* committed the same way an ordinary feedback change is: stage everything but
|
|
70
|
+
* the scratch dir, then commit.
|
|
71
|
+
*/
|
|
72
|
+
export declare function commitAndPush(backend: Backend, workspace: Workspace, message: string): Promise<boolean>;
|
|
53
73
|
//# sourceMappingURL=respond.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"respond.d.ts","sourceRoot":"","sources":["../../src/respond/respond.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"respond.d.ts","sourceRoot":"","sources":["../../src/respond/respond.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEnE,OAAO,KAAK,EAAE,KAAK,EAAyB,MAAM,EAAE,MAAM,EAAY,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAEL,KAAK,OAAO,EAEZ,KAAK,SAAS,EAEf,MAAM,uBAAuB,CAAC;AAG/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,6EAA6E;AAC7E,eAAO,MAAM,aAAa,2BAA2B,CAAC;AAItD,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,cAAc,CAAC;IAC3B;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;iFAC6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAKD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGrE;AAED,MAAM,WAAW,aAAa;IAC5B,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,kFAAkF;IAClF,KAAK,EAAE,WAAW,CAAC;IACnB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEvE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,YAAY,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,GAAG,MAAM,CAGrE;AAYD,6FAA6F;AAC7F,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,aAAa,EAAE,CAAC,CAqC1B;AA2KD;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,OAAO,CAAC,CAgBlB"}
|
package/dist/respond/respond.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { writeWorkspaceFile } from "../backend/fs.js";
|
|
2
2
|
import { mapWithConcurrency } from "../loop/concurrency.js";
|
|
3
3
|
import { GHOSTRAIL_MARKER, gitStageAllArgs, } from "../publish/githost.js";
|
|
4
|
-
import {
|
|
4
|
+
import { resolveConflictsAndMergeSafely } from "./merge.js";
|
|
5
|
+
import { isMergeCommand, latestTimestamp, selectNewComments } from "./select.js";
|
|
5
6
|
/** Where the respond pass drops the human feedback for the agent to read. */
|
|
6
7
|
export const FEEDBACK_PATH = ".ghostrail/feedback.md";
|
|
7
8
|
const nullLogger = { info: () => { }, warn: () => { } };
|
|
@@ -31,26 +32,61 @@ function noopComment(reason) {
|
|
|
31
32
|
return reason === undefined ? opening : `${opening}\n\n${reason}`;
|
|
32
33
|
}
|
|
33
34
|
/** Comment body ghostrail posts, always carrying the marker so it never re-reads its own. */
|
|
34
|
-
function markedComment(body) {
|
|
35
|
+
export function markedComment(body) {
|
|
35
36
|
return `${body}\n\n${GHOSTRAIL_MARKER}`;
|
|
36
37
|
}
|
|
37
38
|
/**
|
|
38
39
|
* The respond pass: for every open factory PR, act only on human comments newer
|
|
39
40
|
* than the per-PR watermark that do not carry the ghostrail marker (so it never
|
|
40
|
-
* acts on its own).
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
41
|
+
* acts on its own). A PR whose fresh comments ask the factory to resolve
|
|
42
|
+
* conflicts and merge (see {@link isMergeCommand}) is routed to that flow
|
|
43
|
+
* instead of the ordinary one; every other PR gets its new feedback handed to
|
|
44
|
+
* the agent, and — on a successful change — committed, pushed to the same
|
|
45
|
+
* branch, and summarized in a comment. The ordinary flow never opens a new PR
|
|
46
|
+
* and never merges. The watermark advances once a PR's new comments have been
|
|
47
|
+
* handled, on every path (success, blocked, or failed).
|
|
44
48
|
*/
|
|
45
49
|
export async function respondTick(deps, config) {
|
|
46
50
|
const logger = deps.logger ?? nullLogger;
|
|
47
51
|
const prs = await deps.host.listOpenPrs(config.label);
|
|
48
52
|
logger.info(`respond: ${prs.length} open ${config.label} PR(s)`);
|
|
53
|
+
// Fresh comments are read once per PR, up front, so the merge-command check
|
|
54
|
+
// below and the flow it dispatches to never re-fetch or re-filter them.
|
|
55
|
+
const withFresh = await mapWithConcurrency(prs, config.guardrails.concurrency, async (pr) => ({
|
|
56
|
+
pr,
|
|
57
|
+
fresh: await freshCommentsFor(deps, config, pr, logger),
|
|
58
|
+
}));
|
|
59
|
+
const mergeRequests = withFresh.filter(({ fresh }) => fresh.some((c) => isMergeCommand(c.body)));
|
|
60
|
+
const normal = withFresh.filter(({ fresh }) => !fresh.some((c) => isMergeCommand(c.body)));
|
|
61
|
+
// Merge requests are pipelined one at a time regardless of the configured
|
|
62
|
+
// concurrency: two of them racing the same base branch would only worsen the
|
|
63
|
+
// conflict situation this feature exists to fix.
|
|
64
|
+
const mergeResults = await mapWithConcurrency(mergeRequests, 1, ({ pr, fresh }) => resolveConflictsAndMergeSafely(deps, config, pr, fresh, logger));
|
|
49
65
|
// Same helper the fix loop and triage use, on the same guardrail. Each PR is
|
|
50
66
|
// an independent agent run of comparable cost and duration, so a sequential
|
|
51
67
|
// pass took as long as the sum of them, and this is the pass a human is most
|
|
52
68
|
// likely to be waiting on: it exists to answer review comments.
|
|
53
|
-
|
|
69
|
+
const normalResults = await mapWithConcurrency(normal, config.guardrails.concurrency, ({ pr, fresh }) => respondToPrSafely(deps, config, pr, fresh, logger));
|
|
70
|
+
const byNumber = new Map([...mergeResults, ...normalResults].map((result) => [result.prNumber, result]));
|
|
71
|
+
return prs
|
|
72
|
+
.map((pr) => byNumber.get(pr.number))
|
|
73
|
+
.filter((result) => result !== undefined);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The human comments a PR's next respond pass should act on: PR comments plus
|
|
77
|
+
* (when a tracker source is wired in) new comments on the issue the PR's
|
|
78
|
+
* branch encodes, filtered to fresh, non-self, unmarked ones.
|
|
79
|
+
*/
|
|
80
|
+
async function freshCommentsFor(deps, config, pr, logger) {
|
|
81
|
+
const prComments = await deps.host.listComments(pr.number);
|
|
82
|
+
const trackerComments = await listTrackerComments(deps, pr, logger);
|
|
83
|
+
const comments = [...prComments, ...trackerComments];
|
|
84
|
+
const since = await deps.watermarks.get(pr.number);
|
|
85
|
+
return selectNewComments(comments, {
|
|
86
|
+
selfLogins: config.selfLogins,
|
|
87
|
+
marker: GHOSTRAIL_MARKER,
|
|
88
|
+
...(since === undefined ? {} : { since }),
|
|
89
|
+
});
|
|
54
90
|
}
|
|
55
91
|
/**
|
|
56
92
|
* `respondToPr`, guaranteed not to throw.
|
|
@@ -61,9 +97,9 @@ export async function respondTick(deps, config) {
|
|
|
61
97
|
* meet it too. One PR whose host lookup fails is one failed result, not a dead
|
|
62
98
|
* pass.
|
|
63
99
|
*/
|
|
64
|
-
async function respondToPrSafely(deps, config, pr, logger) {
|
|
100
|
+
async function respondToPrSafely(deps, config, pr, fresh, logger) {
|
|
65
101
|
try {
|
|
66
|
-
return await respondToPr(deps, config, pr, logger);
|
|
102
|
+
return await respondToPr(deps, config, pr, fresh, logger);
|
|
67
103
|
}
|
|
68
104
|
catch (error) {
|
|
69
105
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -92,16 +128,7 @@ async function listTrackerComments(deps, pr, logger) {
|
|
|
92
128
|
return [];
|
|
93
129
|
}
|
|
94
130
|
}
|
|
95
|
-
async function respondToPr(deps, config, pr, logger) {
|
|
96
|
-
const prComments = await deps.host.listComments(pr.number);
|
|
97
|
-
const trackerComments = await listTrackerComments(deps, pr, logger);
|
|
98
|
-
const comments = [...prComments, ...trackerComments];
|
|
99
|
-
const since = await deps.watermarks.get(pr.number);
|
|
100
|
-
const fresh = selectNewComments(comments, {
|
|
101
|
-
selfLogins: config.selfLogins,
|
|
102
|
-
marker: GHOSTRAIL_MARKER,
|
|
103
|
-
...(since === undefined ? {} : { since }),
|
|
104
|
-
});
|
|
131
|
+
async function respondToPr(deps, config, pr, fresh, logger) {
|
|
105
132
|
if (fresh.length === 0) {
|
|
106
133
|
return { prNumber: pr.number, state: "noop" };
|
|
107
134
|
}
|
|
@@ -161,7 +188,7 @@ async function routeRespond(deps, pr, workspace, outcome, logger) {
|
|
|
161
188
|
await deps.host.postComment(pr.number, markedComment(noopComment(outcome.reason)));
|
|
162
189
|
return { prNumber: pr.number, state: "noop" };
|
|
163
190
|
case "done": {
|
|
164
|
-
const committed = await commitAndPush(deps.backend, workspace);
|
|
191
|
+
const committed = await commitAndPush(deps.backend, workspace, "respond: address review feedback");
|
|
165
192
|
if (!committed) {
|
|
166
193
|
await deps.host.postComment(pr.number, markedComment("No changes were needed for the latest feedback."));
|
|
167
194
|
return { prNumber: pr.number, state: "noop" };
|
|
@@ -172,20 +199,22 @@ async function routeRespond(deps, pr, workspace, outcome, logger) {
|
|
|
172
199
|
}
|
|
173
200
|
}
|
|
174
201
|
}
|
|
175
|
-
/**
|
|
176
|
-
|
|
202
|
+
/**
|
|
203
|
+
* Commit (with `message`) and push the workspace's changes to its branch.
|
|
204
|
+
* Returns false if there was nothing to commit. Shared with the
|
|
205
|
+
* resolve-conflicts-and-merge flow, where `message` names the merge rather
|
|
206
|
+
* than the feedback that prompted it, and a conflicted merge's resolution is
|
|
207
|
+
* committed the same way an ordinary feedback change is: stage everything but
|
|
208
|
+
* the scratch dir, then commit.
|
|
209
|
+
*/
|
|
210
|
+
export async function commitAndPush(backend, workspace, message) {
|
|
177
211
|
for (const args of gitStageAllArgs()) {
|
|
178
212
|
const staged = await backend.exec(workspace, ["git", ...args]);
|
|
179
213
|
if (staged.exitCode !== 0) {
|
|
180
214
|
throw new Error(`git ${args.join(" ")} failed: ${staged.stderr.trim() || staged.stdout.trim()}`);
|
|
181
215
|
}
|
|
182
216
|
}
|
|
183
|
-
const commit = await backend.exec(workspace, [
|
|
184
|
-
"git",
|
|
185
|
-
"commit",
|
|
186
|
-
"-m",
|
|
187
|
-
"respond: address review feedback",
|
|
188
|
-
]);
|
|
217
|
+
const commit = await backend.exec(workspace, ["git", "commit", "-m", message]);
|
|
189
218
|
if (commit.exitCode !== 0)
|
|
190
219
|
return false;
|
|
191
220
|
const push = await backend.exec(workspace, ["git", "push", "origin", workspace.branch]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"respond.js","sourceRoot":"","sources":["../../src/respond/respond.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAGtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,EACL,gBAAgB,EAIhB,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"respond.js","sourceRoot":"","sources":["../../src/respond/respond.ts"],"names":[],"mappings":"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"}
|
package/dist/respond/select.d.ts
CHANGED
|
@@ -14,6 +14,21 @@ export interface SelectOptions {
|
|
|
14
14
|
* Order is preserved.
|
|
15
15
|
*/
|
|
16
16
|
export declare function selectNewComments(comments: readonly PrComment[], options: SelectOptions): PrComment[];
|
|
17
|
+
/**
|
|
18
|
+
* The phrase a human types in a PR or tracker comment to ask the factory to
|
|
19
|
+
* resolve that PR's conflicts with the base branch and merge it. A plain
|
|
20
|
+
* phrase rather than an `@mention` or a `/command`: ghostrail posts through a
|
|
21
|
+
* personal or app token, not a mentionable bot identity, and the comment may
|
|
22
|
+
* come from a GitHub PR or a Linear issue, so the trigger has to read the
|
|
23
|
+
* same in both.
|
|
24
|
+
*/
|
|
25
|
+
export declare const MERGE_COMMAND_PHRASE = "resolve conflicts and merge";
|
|
26
|
+
/**
|
|
27
|
+
* True when `body` asks the factory to resolve conflicts and merge: a
|
|
28
|
+
* case-insensitive substring match, so the phrase can appear anywhere in a
|
|
29
|
+
* longer comment.
|
|
30
|
+
*/
|
|
31
|
+
export declare function isMergeCommand(body: string): boolean;
|
|
17
32
|
/**
|
|
18
33
|
* The latest `createdAt` across the comments (lexicographic max, valid for
|
|
19
34
|
* ISO-8601), or undefined when there are none. Used as the next watermark.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../src/respond/select.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,SAAS,SAAS,EAAE,EAC9B,OAAO,EAAE,aAAa,GACrB,SAAS,EAAE,CAQb;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,GAAG,MAAM,GAAG,SAAS,CAMlF"}
|
|
1
|
+
{"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../src/respond/select.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,SAAS,SAAS,EAAE,EAC9B,OAAO,EAAE,aAAa,GACrB,SAAS,EAAE,CAQb;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,gCAAgC,CAAC;AAElE;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,GAAG,MAAM,GAAG,SAAS,CAMlF"}
|
package/dist/respond/select.js
CHANGED
|
@@ -16,6 +16,23 @@ export function selectNewComments(comments, options) {
|
|
|
16
16
|
return true;
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* The phrase a human types in a PR or tracker comment to ask the factory to
|
|
21
|
+
* resolve that PR's conflicts with the base branch and merge it. A plain
|
|
22
|
+
* phrase rather than an `@mention` or a `/command`: ghostrail posts through a
|
|
23
|
+
* personal or app token, not a mentionable bot identity, and the comment may
|
|
24
|
+
* come from a GitHub PR or a Linear issue, so the trigger has to read the
|
|
25
|
+
* same in both.
|
|
26
|
+
*/
|
|
27
|
+
export const MERGE_COMMAND_PHRASE = "resolve conflicts and merge";
|
|
28
|
+
/**
|
|
29
|
+
* True when `body` asks the factory to resolve conflicts and merge: a
|
|
30
|
+
* case-insensitive substring match, so the phrase can appear anywhere in a
|
|
31
|
+
* longer comment.
|
|
32
|
+
*/
|
|
33
|
+
export function isMergeCommand(body) {
|
|
34
|
+
return body.toLowerCase().includes(MERGE_COMMAND_PHRASE);
|
|
35
|
+
}
|
|
19
36
|
/**
|
|
20
37
|
* The latest `createdAt` across the comments (lexicographic max, valid for
|
|
21
38
|
* ISO-8601), or undefined when there are none. Used as the next watermark.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/respond/select.ts"],"names":[],"mappings":"AAWA;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAA8B,EAC9B,OAAsB;IAEtB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAC7E,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE;QACjC,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAAE,OAAO,KAAK,CAAC;QACzD,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,KAAK,CAAC;QACxD,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QACpF,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAA8B;IAC5D,IAAI,MAA0B,CAAC;IAC/B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,GAAG,MAAM;YAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IACrF,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
1
|
+
{"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/respond/select.ts"],"names":[],"mappings":"AAWA;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAA8B,EAC9B,OAAsB;IAEtB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAC7E,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE;QACjC,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAAE,OAAO,KAAK,CAAC;QACzD,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,KAAK,CAAC;QACxD,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QACpF,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,6BAA6B,CAAC;AAElE;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;AAC3D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAA8B;IAC5D,IAAI,MAA0B,CAAC;IAC/B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,GAAG,MAAM;YAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IACrF,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|