hyper-pm 0.1.3 → 0.1.5
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/README.md +17 -8
- package/dist/index.cjs +687 -75
- package/dist/main.cjs +687 -75
- package/env.example +5 -0
- package/package.json +2 -2
package/dist/main.cjs
CHANGED
|
@@ -7612,6 +7612,20 @@ var envSchema = external_exports.object({
|
|
|
7612
7612
|
HYPER_PM_AI_API_KEY: external_exports.string().optional(),
|
|
7613
7613
|
/** Optional override for hyper-pm JSONL event `actor` on CLI mutations. */
|
|
7614
7614
|
HYPER_PM_ACTOR: external_exports.string().optional(),
|
|
7615
|
+
/**
|
|
7616
|
+
* Optional `git user.name` for hyper-pm data-branch commits when repo git
|
|
7617
|
+
* identity is unset (falls back after `GIT_AUTHOR_*`, then a built-in default).
|
|
7618
|
+
*/
|
|
7619
|
+
HYPER_PM_GIT_USER_NAME: external_exports.string().optional(),
|
|
7620
|
+
/**
|
|
7621
|
+
* Optional `git user.email` for hyper-pm data-branch commits when repo git
|
|
7622
|
+
* identity is unset (falls back after `GIT_AUTHOR_*`, then a built-in default).
|
|
7623
|
+
*/
|
|
7624
|
+
HYPER_PM_GIT_USER_EMAIL: external_exports.string().optional(),
|
|
7625
|
+
/** Standard Git override for commit author name (optional). */
|
|
7626
|
+
GIT_AUTHOR_NAME: external_exports.string().optional(),
|
|
7627
|
+
/** Standard Git override for commit author email (optional). */
|
|
7628
|
+
GIT_AUTHOR_EMAIL: external_exports.string().optional(),
|
|
7615
7629
|
/**
|
|
7616
7630
|
* Absolute path to the hyper-pm CLI bundle (`main.cjs`) for hyper-pm-mcp and
|
|
7617
7631
|
* other integrations when auto-resolution from the `hyper-pm` package is insufficient.
|
|
@@ -11516,6 +11530,103 @@ var normalizeTicketBranchListFromPayloadValue = (value) => {
|
|
|
11516
11530
|
return normalizeTicketBranchListFromStrings(strings);
|
|
11517
11531
|
};
|
|
11518
11532
|
|
|
11533
|
+
// src/lib/ticket-depends-on.ts
|
|
11534
|
+
var normalizeTicketDependsOnIds = (ids) => {
|
|
11535
|
+
const out = [];
|
|
11536
|
+
const seen = /* @__PURE__ */ new Set();
|
|
11537
|
+
for (const raw of ids) {
|
|
11538
|
+
const t = raw.trim();
|
|
11539
|
+
if (t === "") continue;
|
|
11540
|
+
if (seen.has(t)) continue;
|
|
11541
|
+
seen.add(t);
|
|
11542
|
+
out.push(t);
|
|
11543
|
+
}
|
|
11544
|
+
return out;
|
|
11545
|
+
};
|
|
11546
|
+
var ticketDependsOnListsEqual = (a, b) => {
|
|
11547
|
+
const an = normalizeTicketDependsOnIds(a ?? []);
|
|
11548
|
+
const bn = normalizeTicketDependsOnIds(b ?? []);
|
|
11549
|
+
if (an.length !== bn.length) return false;
|
|
11550
|
+
return an.every((x, i) => x === bn[i]);
|
|
11551
|
+
};
|
|
11552
|
+
var parseTicketDependsOnFromPayloadValue = (value) => {
|
|
11553
|
+
if (!Array.isArray(value)) return void 0;
|
|
11554
|
+
const strings = [];
|
|
11555
|
+
for (const x of value) {
|
|
11556
|
+
if (typeof x !== "string") return void 0;
|
|
11557
|
+
strings.push(x);
|
|
11558
|
+
}
|
|
11559
|
+
return normalizeTicketDependsOnIds(strings);
|
|
11560
|
+
};
|
|
11561
|
+
var parseTicketDependsOnFromFenceValue = (value) => {
|
|
11562
|
+
if (!Array.isArray(value)) return void 0;
|
|
11563
|
+
const strings = [];
|
|
11564
|
+
for (const x of value) {
|
|
11565
|
+
if (typeof x === "string") strings.push(x);
|
|
11566
|
+
}
|
|
11567
|
+
return normalizeTicketDependsOnIds(strings);
|
|
11568
|
+
};
|
|
11569
|
+
var wouldTicketDependsOnCreateCycle = (params) => {
|
|
11570
|
+
const { fromTicketId, nextDependsOn, successorsFor } = params;
|
|
11571
|
+
const dfsFromPrerequisite = (start) => {
|
|
11572
|
+
const stack = [start];
|
|
11573
|
+
const visited = /* @__PURE__ */ new Set();
|
|
11574
|
+
while (stack.length > 0) {
|
|
11575
|
+
const node = stack.pop();
|
|
11576
|
+
if (node === fromTicketId) return true;
|
|
11577
|
+
if (visited.has(node)) continue;
|
|
11578
|
+
visited.add(node);
|
|
11579
|
+
const next = successorsFor(node) ?? [];
|
|
11580
|
+
for (let i = next.length - 1; i >= 0; i -= 1) {
|
|
11581
|
+
stack.push(next[i]);
|
|
11582
|
+
}
|
|
11583
|
+
}
|
|
11584
|
+
return false;
|
|
11585
|
+
};
|
|
11586
|
+
for (const p of nextDependsOn) {
|
|
11587
|
+
if (dfsFromPrerequisite(p)) return true;
|
|
11588
|
+
}
|
|
11589
|
+
return false;
|
|
11590
|
+
};
|
|
11591
|
+
var ticketDependsOnSuccessorsForProjection = (projection, fromTicketId, nextDependsOn) => {
|
|
11592
|
+
return (ticketId) => {
|
|
11593
|
+
if (ticketId === fromTicketId) {
|
|
11594
|
+
return nextDependsOn.length > 0 ? nextDependsOn : void 0;
|
|
11595
|
+
}
|
|
11596
|
+
const row = projection.tickets.get(ticketId);
|
|
11597
|
+
if (!row || row.deleted) return void 0;
|
|
11598
|
+
return row.dependsOn;
|
|
11599
|
+
};
|
|
11600
|
+
};
|
|
11601
|
+
var validateTicketDependsOnForWrite = (params) => {
|
|
11602
|
+
const { projection, fromTicketId, nextDependsOn } = params;
|
|
11603
|
+
for (const id of nextDependsOn) {
|
|
11604
|
+
if (id === fromTicketId) {
|
|
11605
|
+
return `Ticket cannot depend on itself (${id})`;
|
|
11606
|
+
}
|
|
11607
|
+
const row = projection.tickets.get(id);
|
|
11608
|
+
if (row === void 0) {
|
|
11609
|
+
return `Dependency ticket not found: ${id}`;
|
|
11610
|
+
}
|
|
11611
|
+
if (row.deleted) {
|
|
11612
|
+
return `Dependency ticket deleted: ${id}`;
|
|
11613
|
+
}
|
|
11614
|
+
}
|
|
11615
|
+
const successorsFor = ticketDependsOnSuccessorsForProjection(
|
|
11616
|
+
projection,
|
|
11617
|
+
fromTicketId,
|
|
11618
|
+
nextDependsOn
|
|
11619
|
+
);
|
|
11620
|
+
if (wouldTicketDependsOnCreateCycle({
|
|
11621
|
+
fromTicketId,
|
|
11622
|
+
nextDependsOn,
|
|
11623
|
+
successorsFor
|
|
11624
|
+
})) {
|
|
11625
|
+
return "Ticket dependencies would create a cycle";
|
|
11626
|
+
}
|
|
11627
|
+
return void 0;
|
|
11628
|
+
};
|
|
11629
|
+
|
|
11519
11630
|
// src/lib/ticket-planning-fields.ts
|
|
11520
11631
|
var PRIORITY_SET = /* @__PURE__ */ new Set([
|
|
11521
11632
|
"low",
|
|
@@ -11684,6 +11795,9 @@ var formatOutput = (format, value) => {
|
|
|
11684
11795
|
return JSON.stringify(value);
|
|
11685
11796
|
};
|
|
11686
11797
|
|
|
11798
|
+
// src/cli/normalize-raw-cli-argv.ts
|
|
11799
|
+
var normalizeRawCliArgv = (argv) => argv.map((token) => token === "--no-github" ? "--skip-network" : token);
|
|
11800
|
+
|
|
11687
11801
|
// src/cli/prune-unchanged-work-item-update-payload.ts
|
|
11688
11802
|
var branchListsEqual = (a, b) => a.length === b.length && a.every((x, i) => x === b[i]);
|
|
11689
11803
|
var pruneEpicOrStoryUpdatePayloadAgainstRow = (cur, draft) => {
|
|
@@ -11739,6 +11853,20 @@ var pruneTicketUpdatePayloadAgainstRow = (cur, draft) => {
|
|
|
11739
11853
|
out["labels"] = draft["labels"];
|
|
11740
11854
|
}
|
|
11741
11855
|
}
|
|
11856
|
+
if (draft["dependsOn"] !== void 0) {
|
|
11857
|
+
if (draft["dependsOn"] === null) {
|
|
11858
|
+
if (!ticketDependsOnListsEqual(cur.dependsOn, [])) {
|
|
11859
|
+
out["dependsOn"] = null;
|
|
11860
|
+
}
|
|
11861
|
+
} else {
|
|
11862
|
+
const parsed = parseTicketDependsOnFromPayloadValue(draft["dependsOn"]);
|
|
11863
|
+
if (parsed !== void 0) {
|
|
11864
|
+
if (!ticketDependsOnListsEqual(cur.dependsOn, parsed)) {
|
|
11865
|
+
out["dependsOn"] = parsed;
|
|
11866
|
+
}
|
|
11867
|
+
}
|
|
11868
|
+
}
|
|
11869
|
+
}
|
|
11742
11870
|
if (draft["priority"] !== void 0) {
|
|
11743
11871
|
const curP = cur.priority ?? null;
|
|
11744
11872
|
const nextP = draft["priority"] === null ? null : draft["priority"];
|
|
@@ -11905,6 +12033,20 @@ var workItemUpdateAspects = (kind, payload) => {
|
|
|
11905
12033
|
}
|
|
11906
12034
|
}
|
|
11907
12035
|
}
|
|
12036
|
+
if (kind === "ticket" && payload["dependsOn"] !== void 0) {
|
|
12037
|
+
if (payload["dependsOn"] === null) {
|
|
12038
|
+
aspects.push("cleared ticket dependencies");
|
|
12039
|
+
} else {
|
|
12040
|
+
const d = normalizeBranchList(payload["dependsOn"]);
|
|
12041
|
+
if (d.length > 0 && d.length <= MAX_BRANCH_NAMES_TO_LIST) {
|
|
12042
|
+
aspects.push(`set ticket dependencies to (${d.join(", ")})`);
|
|
12043
|
+
} else if (d.length > MAX_BRANCH_NAMES_TO_LIST) {
|
|
12044
|
+
aspects.push("updated ticket dependencies");
|
|
12045
|
+
} else {
|
|
12046
|
+
aspects.push("cleared ticket dependencies");
|
|
12047
|
+
}
|
|
12048
|
+
}
|
|
12049
|
+
}
|
|
11908
12050
|
if (kind === "ticket" && payload["priority"] !== void 0) {
|
|
11909
12051
|
if (payload["priority"] === null) {
|
|
11910
12052
|
aspects.push("cleared priority");
|
|
@@ -12011,6 +12153,7 @@ var buildAuditLinkMetadata = (evt, githubRepo) => {
|
|
|
12011
12153
|
if (p["status"] !== void 0) meta["status"] = String(p["status"]);
|
|
12012
12154
|
if (p["assignee"] !== void 0) meta["assignee"] = p["assignee"];
|
|
12013
12155
|
if (p["labels"] !== void 0) meta["labels"] = p["labels"];
|
|
12156
|
+
if (p["dependsOn"] !== void 0) meta["dependsOn"] = p["dependsOn"];
|
|
12014
12157
|
if (p["priority"] !== void 0) meta["priority"] = p["priority"];
|
|
12015
12158
|
if (p["size"] !== void 0) meta["size"] = p["size"];
|
|
12016
12159
|
if (p["estimate"] !== void 0) meta["estimate"] = p["estimate"];
|
|
@@ -12078,6 +12221,14 @@ var formatEpicStoryTicketCreated = (evt, entity) => {
|
|
|
12078
12221
|
parts.push("with labels");
|
|
12079
12222
|
}
|
|
12080
12223
|
}
|
|
12224
|
+
if (p["dependsOn"] !== void 0) {
|
|
12225
|
+
const d = normalizeBranchList(p["dependsOn"]);
|
|
12226
|
+
if (d.length > 0 && d.length <= MAX_BRANCH_NAMES_TO_LIST) {
|
|
12227
|
+
parts.push(`depending on (${d.join(", ")})`);
|
|
12228
|
+
} else if (d.length > MAX_BRANCH_NAMES_TO_LIST) {
|
|
12229
|
+
parts.push("with ticket dependencies");
|
|
12230
|
+
}
|
|
12231
|
+
}
|
|
12081
12232
|
if (p["priority"] !== void 0) {
|
|
12082
12233
|
parts.push(`with priority ${quoteStatus(String(p["priority"]))}`);
|
|
12083
12234
|
}
|
|
@@ -12171,6 +12322,18 @@ var formatAuditHumanSentence = (evt) => {
|
|
|
12171
12322
|
bits.push("updated labels");
|
|
12172
12323
|
}
|
|
12173
12324
|
}
|
|
12325
|
+
if (p["dependsOn"] !== void 0) {
|
|
12326
|
+
if (p["dependsOn"] === null) {
|
|
12327
|
+
bits.push("cleared ticket dependencies");
|
|
12328
|
+
} else {
|
|
12329
|
+
const d = normalizeBranchList(p["dependsOn"]);
|
|
12330
|
+
if (d.length > 0 && d.length <= MAX_BRANCH_NAMES_TO_LIST) {
|
|
12331
|
+
bits.push(`dependencies: ${d.join(", ")}`);
|
|
12332
|
+
} else {
|
|
12333
|
+
bits.push("updated ticket dependencies");
|
|
12334
|
+
}
|
|
12335
|
+
}
|
|
12336
|
+
}
|
|
12174
12337
|
if (p["priority"] !== void 0) {
|
|
12175
12338
|
bits.push("updated priority");
|
|
12176
12339
|
}
|
|
@@ -12450,6 +12613,13 @@ var ticketMatchesTicketListQuery = (ticket, projection, query) => {
|
|
|
12450
12613
|
return false;
|
|
12451
12614
|
}
|
|
12452
12615
|
}
|
|
12616
|
+
const dependsOnIncludesId = query.dependsOnIncludesId;
|
|
12617
|
+
if (dependsOnIncludesId !== void 0) {
|
|
12618
|
+
const deps = ticket.dependsOn ?? [];
|
|
12619
|
+
if (!deps.includes(dependsOnIncludesId)) {
|
|
12620
|
+
return false;
|
|
12621
|
+
}
|
|
12622
|
+
}
|
|
12453
12623
|
return true;
|
|
12454
12624
|
};
|
|
12455
12625
|
|
|
@@ -12655,6 +12825,7 @@ var listActiveTicketSummaries = (projection, options) => {
|
|
|
12655
12825
|
...t.estimate !== void 0 ? { estimate: t.estimate } : {},
|
|
12656
12826
|
...t.startWorkAt !== void 0 ? { startWorkAt: t.startWorkAt } : {},
|
|
12657
12827
|
...t.targetFinishAt !== void 0 ? { targetFinishAt: t.targetFinishAt } : {},
|
|
12828
|
+
...t.dependsOn !== void 0 && t.dependsOn.length > 0 ? { dependsOn: t.dependsOn } : {},
|
|
12658
12829
|
...t.linkedBranches.length > 0 ? { linkedBranches: t.linkedBranches } : {},
|
|
12659
12830
|
...last !== void 0 ? {
|
|
12660
12831
|
lastPrActivity: {
|
|
@@ -12751,6 +12922,17 @@ var inboundTicketPlanningPayloadFromFenceMeta = (meta) => {
|
|
|
12751
12922
|
}
|
|
12752
12923
|
}
|
|
12753
12924
|
}
|
|
12925
|
+
if (Object.prototype.hasOwnProperty.call(meta, "depends_on")) {
|
|
12926
|
+
const v = meta["depends_on"];
|
|
12927
|
+
if (v === null) {
|
|
12928
|
+
out["dependsOn"] = null;
|
|
12929
|
+
} else {
|
|
12930
|
+
const parsed = parseTicketDependsOnFromFenceValue(v);
|
|
12931
|
+
if (parsed !== void 0) {
|
|
12932
|
+
out["dependsOn"] = parsed;
|
|
12933
|
+
}
|
|
12934
|
+
}
|
|
12935
|
+
}
|
|
12754
12936
|
return out;
|
|
12755
12937
|
};
|
|
12756
12938
|
var buildGithubIssueBody = (params) => {
|
|
@@ -12776,6 +12958,9 @@ var buildGithubIssueBody = (params) => {
|
|
|
12776
12958
|
if (p.targetFinishAt !== void 0) {
|
|
12777
12959
|
meta.target_finish_at = p.targetFinishAt;
|
|
12778
12960
|
}
|
|
12961
|
+
if (p.dependsOn !== void 0 && p.dependsOn.length > 0) {
|
|
12962
|
+
meta.depends_on = p.dependsOn;
|
|
12963
|
+
}
|
|
12779
12964
|
}
|
|
12780
12965
|
return `${params.description.trim()}
|
|
12781
12966
|
|
|
@@ -12801,6 +12986,9 @@ var ticketPlanningForGithubIssueBody = (ticket) => {
|
|
|
12801
12986
|
if (ticket.targetFinishAt !== void 0) {
|
|
12802
12987
|
out.targetFinishAt = ticket.targetFinishAt;
|
|
12803
12988
|
}
|
|
12989
|
+
if (ticket.dependsOn !== void 0 && ticket.dependsOn.length > 0) {
|
|
12990
|
+
out.dependsOn = ticket.dependsOn;
|
|
12991
|
+
}
|
|
12804
12992
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
12805
12993
|
};
|
|
12806
12994
|
|
|
@@ -13353,6 +13541,33 @@ var tryReadGithubOwnerRepoSlugFromGit = async (params) => {
|
|
|
13353
13541
|
}
|
|
13354
13542
|
};
|
|
13355
13543
|
|
|
13544
|
+
// src/git/resolve-effective-git-author-for-data-commit.ts
|
|
13545
|
+
var defaultDataCommitName = "hyper-pm";
|
|
13546
|
+
var defaultDataCommitEmail = "hyper-pm@users.noreply.github.com";
|
|
13547
|
+
var tryReadGitConfigUserName = async (cwd, runGit2) => {
|
|
13548
|
+
try {
|
|
13549
|
+
const { stdout } = await runGit2(cwd, ["config", "--get", "user.name"]);
|
|
13550
|
+
return stdout.trim();
|
|
13551
|
+
} catch {
|
|
13552
|
+
return "";
|
|
13553
|
+
}
|
|
13554
|
+
};
|
|
13555
|
+
var tryReadGitConfigUserEmail = async (cwd, runGit2) => {
|
|
13556
|
+
try {
|
|
13557
|
+
const { stdout } = await runGit2(cwd, ["config", "--get", "user.email"]);
|
|
13558
|
+
return stdout.trim();
|
|
13559
|
+
} catch {
|
|
13560
|
+
return "";
|
|
13561
|
+
}
|
|
13562
|
+
};
|
|
13563
|
+
var resolveEffectiveGitAuthorForDataCommit = async (cwd, runGit2, authorEnv) => {
|
|
13564
|
+
const fromGitName = await tryReadGitConfigUserName(cwd, runGit2);
|
|
13565
|
+
const fromGitEmail = await tryReadGitConfigUserEmail(cwd, runGit2);
|
|
13566
|
+
const name = fromGitName || authorEnv.HYPER_PM_GIT_USER_NAME?.trim() || authorEnv.GIT_AUTHOR_NAME?.trim() || defaultDataCommitName;
|
|
13567
|
+
const email = fromGitEmail || authorEnv.HYPER_PM_GIT_USER_EMAIL?.trim() || authorEnv.GIT_AUTHOR_EMAIL?.trim() || defaultDataCommitEmail;
|
|
13568
|
+
return { name, email };
|
|
13569
|
+
};
|
|
13570
|
+
|
|
13356
13571
|
// src/run/commit-data.ts
|
|
13357
13572
|
var maxActorSuffixLen = 60;
|
|
13358
13573
|
var formatDataBranchCommitMessage = (base, actorSuffix) => {
|
|
@@ -13364,11 +13579,205 @@ var formatDataBranchCommitMessage = (base, actorSuffix) => {
|
|
|
13364
13579
|
const suffix = collapsed.length > maxActorSuffixLen ? `${collapsed.slice(0, maxActorSuffixLen - 1)}\u2026` : collapsed;
|
|
13365
13580
|
return `${base} (${suffix})`;
|
|
13366
13581
|
};
|
|
13367
|
-
var commitDataWorktreeIfNeeded = async (worktreePath, message, runGit2) => {
|
|
13582
|
+
var commitDataWorktreeIfNeeded = async (worktreePath, message, runGit2, opts) => {
|
|
13368
13583
|
const { stdout } = await runGit2(worktreePath, ["status", "--porcelain"]);
|
|
13369
13584
|
if (!stdout.trim()) return;
|
|
13370
13585
|
await runGit2(worktreePath, ["add", "."]);
|
|
13371
|
-
|
|
13586
|
+
const authorEnv = opts?.authorEnv ?? env;
|
|
13587
|
+
const { name, email } = await resolveEffectiveGitAuthorForDataCommit(
|
|
13588
|
+
worktreePath,
|
|
13589
|
+
runGit2,
|
|
13590
|
+
authorEnv
|
|
13591
|
+
);
|
|
13592
|
+
await runGit2(worktreePath, [
|
|
13593
|
+
"-c",
|
|
13594
|
+
`user.name=${name}`,
|
|
13595
|
+
"-c",
|
|
13596
|
+
`user.email=${email}`,
|
|
13597
|
+
"commit",
|
|
13598
|
+
"-m",
|
|
13599
|
+
message
|
|
13600
|
+
]);
|
|
13601
|
+
};
|
|
13602
|
+
|
|
13603
|
+
// src/run/push-data-branch.ts
|
|
13604
|
+
var firstLineFromUnknown = (err) => {
|
|
13605
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
13606
|
+
const line = raw.trim().split("\n")[0]?.trim() ?? raw.trim();
|
|
13607
|
+
return line.length > 0 ? line : "git error";
|
|
13608
|
+
};
|
|
13609
|
+
var tryPushDataBranchToRemote = async (worktreePath, remote, branch, runGit2) => {
|
|
13610
|
+
try {
|
|
13611
|
+
await runGit2(worktreePath, ["remote", "get-url", remote]);
|
|
13612
|
+
} catch (e) {
|
|
13613
|
+
return {
|
|
13614
|
+
status: "skipped_no_remote",
|
|
13615
|
+
detail: firstLineFromUnknown(e)
|
|
13616
|
+
};
|
|
13617
|
+
}
|
|
13618
|
+
try {
|
|
13619
|
+
await runGit2(worktreePath, ["push", "-u", remote, branch]);
|
|
13620
|
+
return { status: "pushed" };
|
|
13621
|
+
} catch (e) {
|
|
13622
|
+
return {
|
|
13623
|
+
status: "failed",
|
|
13624
|
+
detail: firstLineFromUnknown(e)
|
|
13625
|
+
};
|
|
13626
|
+
}
|
|
13627
|
+
};
|
|
13628
|
+
|
|
13629
|
+
// src/run/sync-remote-data-branch.ts
|
|
13630
|
+
var SyncRemoteDataBranchMergeError = class extends Error {
|
|
13631
|
+
/** @param message - Human-readable reason (stderr excerpt or generic text). */
|
|
13632
|
+
constructor(message) {
|
|
13633
|
+
super(message);
|
|
13634
|
+
this.name = "SyncRemoteDataBranchMergeError";
|
|
13635
|
+
}
|
|
13636
|
+
};
|
|
13637
|
+
var remoteTrackingRef = (remote, dataBranch) => `refs/remotes/${remote}/${dataBranch}`;
|
|
13638
|
+
var mergeRefSpecifier = (remote, dataBranch) => `${remote}/${dataBranch}`;
|
|
13639
|
+
var isLikelyNonFastForwardPushFailure = (detail) => {
|
|
13640
|
+
if (detail === void 0) return false;
|
|
13641
|
+
const d = detail.toLowerCase();
|
|
13642
|
+
return d.includes("non-fast-forward") || d.includes("failed to push");
|
|
13643
|
+
};
|
|
13644
|
+
var classifyMergeOutput = (combined) => {
|
|
13645
|
+
const c = combined.toLowerCase();
|
|
13646
|
+
if (c.includes("already up to date")) {
|
|
13647
|
+
return "up_to_date";
|
|
13648
|
+
}
|
|
13649
|
+
if (c.includes("fast-forward")) {
|
|
13650
|
+
return "fast_forward";
|
|
13651
|
+
}
|
|
13652
|
+
return "merge_commit";
|
|
13653
|
+
};
|
|
13654
|
+
var refExists = async (cwd, ref, runGit2) => {
|
|
13655
|
+
try {
|
|
13656
|
+
await runGit2(cwd, ["show-ref", "--verify", "--quiet", ref]);
|
|
13657
|
+
return true;
|
|
13658
|
+
} catch {
|
|
13659
|
+
return false;
|
|
13660
|
+
}
|
|
13661
|
+
};
|
|
13662
|
+
var fetchRemoteDataBranch = async (worktreePath, remote, dataBranch, runGit2) => {
|
|
13663
|
+
try {
|
|
13664
|
+
await runGit2(worktreePath, ["remote", "get-url", remote]);
|
|
13665
|
+
} catch {
|
|
13666
|
+
return "skipped_no_remote";
|
|
13667
|
+
}
|
|
13668
|
+
try {
|
|
13669
|
+
await runGit2(worktreePath, ["fetch", remote, dataBranch]);
|
|
13670
|
+
return "ok";
|
|
13671
|
+
} catch (e) {
|
|
13672
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
13673
|
+
if (/couldn't find remote ref|could not find remote ref/i.test(msg)) {
|
|
13674
|
+
return "remote_branch_absent";
|
|
13675
|
+
}
|
|
13676
|
+
throw e;
|
|
13677
|
+
}
|
|
13678
|
+
};
|
|
13679
|
+
var mergeRemoteTrackingIntoHead = async (worktreePath, remote, dataBranch, runGit2, authorEnv = env) => {
|
|
13680
|
+
const spec = mergeRefSpecifier(remote, dataBranch);
|
|
13681
|
+
const { name, email } = await resolveEffectiveGitAuthorForDataCommit(
|
|
13682
|
+
worktreePath,
|
|
13683
|
+
runGit2,
|
|
13684
|
+
authorEnv
|
|
13685
|
+
);
|
|
13686
|
+
try {
|
|
13687
|
+
const { stdout, stderr } = await runGit2(worktreePath, [
|
|
13688
|
+
"-c",
|
|
13689
|
+
`user.name=${name}`,
|
|
13690
|
+
"-c",
|
|
13691
|
+
`user.email=${email}`,
|
|
13692
|
+
"merge",
|
|
13693
|
+
"--no-edit",
|
|
13694
|
+
spec
|
|
13695
|
+
]);
|
|
13696
|
+
return classifyMergeOutput(`${stdout}
|
|
13697
|
+
${stderr}`);
|
|
13698
|
+
} catch (e) {
|
|
13699
|
+
await runGit2(worktreePath, ["merge", "--abort"]).catch(() => {
|
|
13700
|
+
});
|
|
13701
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
13702
|
+
throw new SyncRemoteDataBranchMergeError(
|
|
13703
|
+
msg.toLowerCase().includes("conflict") ? "Merge conflict while syncing hyper-pm data branch; merge aborted. Resolve manually on the data branch if needed." : `git merge failed: ${msg.trim().split("\n")[0] ?? msg}`
|
|
13704
|
+
);
|
|
13705
|
+
}
|
|
13706
|
+
};
|
|
13707
|
+
var runRemoteDataBranchGitSync = async (worktreePath, remote, dataBranch, runGit2, skipPush, deps = {}) => {
|
|
13708
|
+
const tryPushFn = deps.tryPush ?? tryPushDataBranchToRemote;
|
|
13709
|
+
const maxPushAttempts = deps.maxPushAttempts ?? 3;
|
|
13710
|
+
const authorEnv = deps.authorEnv ?? env;
|
|
13711
|
+
let dataBranchFetch = await fetchRemoteDataBranch(worktreePath, remote, dataBranch, runGit2);
|
|
13712
|
+
let dataBranchMerge = dataBranchFetch === "skipped_no_remote" ? "skipped_no_remote" : dataBranchFetch === "remote_branch_absent" ? "skipped_missing_remote_branch" : "up_to_date";
|
|
13713
|
+
if (dataBranchFetch === "ok") {
|
|
13714
|
+
const tracking = remoteTrackingRef(remote, dataBranch);
|
|
13715
|
+
const exists = await refExists(worktreePath, tracking, runGit2);
|
|
13716
|
+
if (!exists) {
|
|
13717
|
+
dataBranchMerge = "skipped_missing_remote_branch";
|
|
13718
|
+
} else {
|
|
13719
|
+
dataBranchMerge = await mergeRemoteTrackingIntoHead(
|
|
13720
|
+
worktreePath,
|
|
13721
|
+
remote,
|
|
13722
|
+
dataBranch,
|
|
13723
|
+
runGit2,
|
|
13724
|
+
authorEnv
|
|
13725
|
+
);
|
|
13726
|
+
}
|
|
13727
|
+
}
|
|
13728
|
+
if (skipPush) {
|
|
13729
|
+
return {
|
|
13730
|
+
dataBranchFetch,
|
|
13731
|
+
dataBranchMerge,
|
|
13732
|
+
dataBranchPush: "skipped_cli",
|
|
13733
|
+
dataBranchPushDetail: "skip-push",
|
|
13734
|
+
pushAttempts: 0
|
|
13735
|
+
};
|
|
13736
|
+
}
|
|
13737
|
+
let pushAttempts = 0;
|
|
13738
|
+
let lastPush = { status: "skipped_no_remote" };
|
|
13739
|
+
const refetchAndMerge = async () => {
|
|
13740
|
+
dataBranchFetch = await fetchRemoteDataBranch(
|
|
13741
|
+
worktreePath,
|
|
13742
|
+
remote,
|
|
13743
|
+
dataBranch,
|
|
13744
|
+
runGit2
|
|
13745
|
+
);
|
|
13746
|
+
if (dataBranchFetch !== "ok") {
|
|
13747
|
+
return;
|
|
13748
|
+
}
|
|
13749
|
+
const tracking = remoteTrackingRef(remote, dataBranch);
|
|
13750
|
+
const exists = await refExists(worktreePath, tracking, runGit2);
|
|
13751
|
+
if (!exists) {
|
|
13752
|
+
return;
|
|
13753
|
+
}
|
|
13754
|
+
dataBranchMerge = await mergeRemoteTrackingIntoHead(
|
|
13755
|
+
worktreePath,
|
|
13756
|
+
remote,
|
|
13757
|
+
dataBranch,
|
|
13758
|
+
runGit2,
|
|
13759
|
+
authorEnv
|
|
13760
|
+
);
|
|
13761
|
+
};
|
|
13762
|
+
for (let attempt = 1; attempt <= maxPushAttempts; attempt += 1) {
|
|
13763
|
+
pushAttempts = attempt;
|
|
13764
|
+
lastPush = await tryPushFn(worktreePath, remote, dataBranch, runGit2);
|
|
13765
|
+
if (lastPush.status === "pushed" || lastPush.status === "skipped_no_remote") {
|
|
13766
|
+
break;
|
|
13767
|
+
}
|
|
13768
|
+
if (lastPush.status === "failed" && isLikelyNonFastForwardPushFailure(lastPush.detail) && attempt < maxPushAttempts) {
|
|
13769
|
+
await refetchAndMerge();
|
|
13770
|
+
continue;
|
|
13771
|
+
}
|
|
13772
|
+
break;
|
|
13773
|
+
}
|
|
13774
|
+
return {
|
|
13775
|
+
dataBranchFetch,
|
|
13776
|
+
dataBranchMerge,
|
|
13777
|
+
dataBranchPush: lastPush.status,
|
|
13778
|
+
...lastPush.detail !== void 0 ? { dataBranchPushDetail: lastPush.detail } : {},
|
|
13779
|
+
pushAttempts
|
|
13780
|
+
};
|
|
13372
13781
|
};
|
|
13373
13782
|
|
|
13374
13783
|
// src/storage/append-event.ts
|
|
@@ -13566,6 +13975,12 @@ var applyTicketPlanningFieldsFromCreatePayload = (row, payload) => {
|
|
|
13566
13975
|
if (typeof tf === "string") {
|
|
13567
13976
|
row.targetFinishAt = tf;
|
|
13568
13977
|
}
|
|
13978
|
+
if (Object.prototype.hasOwnProperty.call(payload, "dependsOn")) {
|
|
13979
|
+
const v = parseTicketDependsOnFromPayloadValue(payload["dependsOn"]);
|
|
13980
|
+
if (v !== void 0 && v.length > 0) {
|
|
13981
|
+
row.dependsOn = v;
|
|
13982
|
+
}
|
|
13983
|
+
}
|
|
13569
13984
|
};
|
|
13570
13985
|
var applyTicketPlanningFieldsFromUpdatePayload = (row, payload) => {
|
|
13571
13986
|
if (Object.prototype.hasOwnProperty.call(payload, "labels")) {
|
|
@@ -13612,6 +14027,20 @@ var applyTicketPlanningFieldsFromUpdatePayload = (row, payload) => {
|
|
|
13612
14027
|
} else if (typeof tf === "string") {
|
|
13613
14028
|
row.targetFinishAt = tf;
|
|
13614
14029
|
}
|
|
14030
|
+
if (Object.prototype.hasOwnProperty.call(payload, "dependsOn")) {
|
|
14031
|
+
if (payload["dependsOn"] === null) {
|
|
14032
|
+
delete row.dependsOn;
|
|
14033
|
+
} else {
|
|
14034
|
+
const v = parseTicketDependsOnFromPayloadValue(payload["dependsOn"]);
|
|
14035
|
+
if (v !== void 0) {
|
|
14036
|
+
if (v.length === 0) {
|
|
14037
|
+
delete row.dependsOn;
|
|
14038
|
+
} else {
|
|
14039
|
+
row.dependsOn = v;
|
|
14040
|
+
}
|
|
14041
|
+
}
|
|
14042
|
+
}
|
|
14043
|
+
}
|
|
13615
14044
|
};
|
|
13616
14045
|
var applyCreatedAudit = (row, evt) => {
|
|
13617
14046
|
row.createdAt = evt.ts;
|
|
@@ -14238,6 +14667,19 @@ var runGithubInboundSync = async (params) => {
|
|
|
14238
14667
|
const planningSource = inboundTicketPlanningPayloadFromFenceMeta(meta);
|
|
14239
14668
|
const planningPayload = {};
|
|
14240
14669
|
for (const [k, v] of Object.entries(planningSource)) {
|
|
14670
|
+
if (k === "dependsOn") {
|
|
14671
|
+
if (v === null) {
|
|
14672
|
+
if (!ticketDependsOnListsEqual(ticket.dependsOn, [])) {
|
|
14673
|
+
planningPayload["dependsOn"] = null;
|
|
14674
|
+
}
|
|
14675
|
+
} else if (Array.isArray(v)) {
|
|
14676
|
+
const parsed = parseTicketDependsOnFromPayloadValue(v);
|
|
14677
|
+
if (parsed !== void 0 && !ticketDependsOnListsEqual(ticket.dependsOn, parsed)) {
|
|
14678
|
+
planningPayload["dependsOn"] = parsed;
|
|
14679
|
+
}
|
|
14680
|
+
}
|
|
14681
|
+
continue;
|
|
14682
|
+
}
|
|
14241
14683
|
const tk = k;
|
|
14242
14684
|
const cur = ticket[tk];
|
|
14243
14685
|
if (v === null) {
|
|
@@ -14575,6 +15017,9 @@ var buildTicketListQueryFromReadListOpts = (o, deps) => {
|
|
|
14575
15017
|
if (targetFinishBeforeMs !== void 0) {
|
|
14576
15018
|
query.targetFinishBeforeMs = targetFinishBeforeMs;
|
|
14577
15019
|
}
|
|
15020
|
+
if (o.dependsOn !== void 0 && o.dependsOn.trim() !== "") {
|
|
15021
|
+
query.dependsOnIncludesId = o.dependsOn.trim();
|
|
15022
|
+
}
|
|
14578
15023
|
return Object.keys(query).length > 0 ? query : void 0;
|
|
14579
15024
|
};
|
|
14580
15025
|
var runCli = async (argv, deps = {
|
|
@@ -14798,6 +15243,11 @@ var runCli = async (argv, deps = {
|
|
|
14798
15243
|
"planning label (repeatable)",
|
|
14799
15244
|
(value, previous) => [...previous, value],
|
|
14800
15245
|
[]
|
|
15246
|
+
).option(
|
|
15247
|
+
"--depends-on <id>",
|
|
15248
|
+
"prerequisite ticket id (repeatable)",
|
|
15249
|
+
(value, previous) => [...previous, value],
|
|
15250
|
+
[]
|
|
14801
15251
|
).option("--priority <p>", "low|medium|high|urgent").option("--size <s>", "xs|s|m|l|xl").option("--estimate <n>", "non-negative estimate (e.g. story points)").option("--start-at <iso>", "planned start work at (ISO-8601)").option("--target-finish-at <iso>", "planned target finish at (ISO-8601)").option("--ai-draft", "draft body via AI (explicit)", false).action(async function() {
|
|
14802
15252
|
const g = readGlobals(this);
|
|
14803
15253
|
const o = this.opts();
|
|
@@ -14860,6 +15310,10 @@ var runCli = async (argv, deps = {
|
|
|
14860
15310
|
"--target-finish-at",
|
|
14861
15311
|
deps
|
|
14862
15312
|
);
|
|
15313
|
+
const dependsOnTokensCreate = normalizeCliStringList(o.dependsOn);
|
|
15314
|
+
const dependsOnNormCreate = normalizeTicketDependsOnIds(
|
|
15315
|
+
dependsOnTokensCreate
|
|
15316
|
+
);
|
|
14863
15317
|
const planningPayload = {
|
|
14864
15318
|
...labelsPayloadCreate,
|
|
14865
15319
|
...priorityParsed !== void 0 ? { priority: priorityParsed } : {},
|
|
@@ -14886,6 +15340,15 @@ var runCli = async (argv, deps = {
|
|
|
14886
15340
|
const branchTokens = normalizeCliStringList(o.branch);
|
|
14887
15341
|
const branchesNorm = normalizeTicketBranchListFromStrings(branchTokens);
|
|
14888
15342
|
const branchesPayload = branchesNorm.length > 0 ? { branches: branchesNorm } : {};
|
|
15343
|
+
const dependsOnErr = validateTicketDependsOnForWrite({
|
|
15344
|
+
projection: proj,
|
|
15345
|
+
fromTicketId: id,
|
|
15346
|
+
nextDependsOn: dependsOnNormCreate
|
|
15347
|
+
});
|
|
15348
|
+
if (dependsOnErr !== void 0) {
|
|
15349
|
+
throw new Error(dependsOnErr);
|
|
15350
|
+
}
|
|
15351
|
+
const dependsOnPayloadCreate = dependsOnNormCreate.length > 0 ? { dependsOn: dependsOnNormCreate } : {};
|
|
14889
15352
|
const evt = makeEvent(
|
|
14890
15353
|
"TicketCreated",
|
|
14891
15354
|
{
|
|
@@ -14896,6 +15359,7 @@ var runCli = async (argv, deps = {
|
|
|
14896
15359
|
...status !== void 0 ? { status } : {},
|
|
14897
15360
|
...assigneeCreate,
|
|
14898
15361
|
...branchesPayload,
|
|
15362
|
+
...dependsOnPayloadCreate,
|
|
14899
15363
|
...planningPayload
|
|
14900
15364
|
},
|
|
14901
15365
|
deps.clock,
|
|
@@ -14953,6 +15417,9 @@ var runCli = async (argv, deps = {
|
|
|
14953
15417
|
).option(
|
|
14954
15418
|
"--branch <name>",
|
|
14955
15419
|
"when listing (no --id): only tickets linked to this branch (normalized exact match)"
|
|
15420
|
+
).option(
|
|
15421
|
+
"--depends-on <id>",
|
|
15422
|
+
"when listing (no --id): only tickets that list this ticket id in dependsOn"
|
|
14956
15423
|
).option(
|
|
14957
15424
|
"--priority <p>",
|
|
14958
15425
|
"when listing (no --id): OR-set of priorities (repeat flag); low|medium|high|urgent",
|
|
@@ -15032,7 +15499,17 @@ var runCli = async (argv, deps = {
|
|
|
15032
15499
|
"--clear-labels",
|
|
15033
15500
|
"remove all planning labels from the ticket",
|
|
15034
15501
|
false
|
|
15035
|
-
).option(
|
|
15502
|
+
).option(
|
|
15503
|
+
"--add-depends-on <id>",
|
|
15504
|
+
"add a prerequisite ticket id (repeatable)",
|
|
15505
|
+
(value, previous) => [...previous, value],
|
|
15506
|
+
[]
|
|
15507
|
+
).option(
|
|
15508
|
+
"--remove-depends-on <id>",
|
|
15509
|
+
"remove a prerequisite ticket id (repeatable)",
|
|
15510
|
+
(value, previous) => [...previous, value],
|
|
15511
|
+
[]
|
|
15512
|
+
).option("--clear-depends-on", "remove all ticket dependencies", false).option("--priority <p>", "low|medium|high|urgent").option("--clear-priority", "remove priority", false).option("--size <s>", "xs|s|m|l|xl").option("--clear-size", "remove size", false).option("--estimate <n>", "non-negative estimate (e.g. story points)").option("--clear-estimate", "remove estimate", false).option("--start-at <iso>", "planned start work at (ISO-8601)").option("--clear-start-at", "remove start work date", false).option("--target-finish-at <iso>", "planned target finish at (ISO-8601)").option("--clear-target-finish-at", "remove target finish date", false).option("--ai-improve", "expand description via AI (explicit)", false).action(async function() {
|
|
15036
15513
|
const g = readGlobals(this);
|
|
15037
15514
|
const o = this.opts();
|
|
15038
15515
|
let body = o.body;
|
|
@@ -15084,6 +15561,14 @@ ${body}`
|
|
|
15084
15561
|
);
|
|
15085
15562
|
deps.exit(ExitCode.UserError);
|
|
15086
15563
|
}
|
|
15564
|
+
const addDependsOnTokens = normalizeCliStringList(o.addDependsOn);
|
|
15565
|
+
const removeDependsOnTokens = normalizeCliStringList(o.removeDependsOn);
|
|
15566
|
+
if (o.clearDependsOn === true && (addDependsOnTokens.length > 0 || removeDependsOnTokens.length > 0)) {
|
|
15567
|
+
deps.error(
|
|
15568
|
+
"Cannot use --clear-depends-on with --add-depends-on or --remove-depends-on"
|
|
15569
|
+
);
|
|
15570
|
+
deps.exit(ExitCode.UserError);
|
|
15571
|
+
}
|
|
15087
15572
|
const mutual = (clear, set, clearName, setName) => {
|
|
15088
15573
|
if (clear === true && set !== void 0 && set !== "") {
|
|
15089
15574
|
deps.error(`Cannot use ${clearName} and ${setName} together`);
|
|
@@ -15216,6 +15701,35 @@ ${body}`
|
|
|
15216
15701
|
payload["labels"] = nextLabels;
|
|
15217
15702
|
}
|
|
15218
15703
|
}
|
|
15704
|
+
const wantsDependsOnChange = o.clearDependsOn === true || addDependsOnTokens.length > 0 || removeDependsOnTokens.length > 0;
|
|
15705
|
+
if (wantsDependsOnChange) {
|
|
15706
|
+
let nextDepends;
|
|
15707
|
+
if (o.clearDependsOn === true) {
|
|
15708
|
+
nextDepends = [];
|
|
15709
|
+
} else {
|
|
15710
|
+
const removeDepSet = new Set(
|
|
15711
|
+
normalizeTicketDependsOnIds(removeDependsOnTokens)
|
|
15712
|
+
);
|
|
15713
|
+
nextDepends = normalizeTicketDependsOnIds(
|
|
15714
|
+
(curTicket.dependsOn ?? []).filter((d) => !removeDepSet.has(d))
|
|
15715
|
+
);
|
|
15716
|
+
nextDepends = normalizeTicketDependsOnIds([
|
|
15717
|
+
...nextDepends,
|
|
15718
|
+
...addDependsOnTokens
|
|
15719
|
+
]);
|
|
15720
|
+
}
|
|
15721
|
+
const depErr = validateTicketDependsOnForWrite({
|
|
15722
|
+
projection: proj,
|
|
15723
|
+
fromTicketId: o.id,
|
|
15724
|
+
nextDependsOn: nextDepends
|
|
15725
|
+
});
|
|
15726
|
+
if (depErr !== void 0) {
|
|
15727
|
+
throw new Error(depErr);
|
|
15728
|
+
}
|
|
15729
|
+
if (!ticketDependsOnListsEqual(curTicket.dependsOn, nextDepends)) {
|
|
15730
|
+
payload["dependsOn"] = nextDepends;
|
|
15731
|
+
}
|
|
15732
|
+
}
|
|
15219
15733
|
if (priorityUpdate !== void 0) {
|
|
15220
15734
|
payload["priority"] = priorityUpdate;
|
|
15221
15735
|
}
|
|
@@ -15529,94 +16043,192 @@ ${body}`
|
|
|
15529
16043
|
}
|
|
15530
16044
|
deps.exit(ExitCode.Success);
|
|
15531
16045
|
});
|
|
15532
|
-
program2.command("sync").description("GitHub Issues sync").option(
|
|
16046
|
+
program2.command("sync").description("Sync data branch over git; optional GitHub Issues sync").option(
|
|
16047
|
+
"--skip-network",
|
|
16048
|
+
"skip all sync network operations (git fetch/merge/push and GitHub); legacy: --no-github",
|
|
16049
|
+
false
|
|
16050
|
+
).option(
|
|
16051
|
+
"--with-github",
|
|
16052
|
+
"also run GitHub Issues sync (requires GITHUB_TOKEN or gh; needs sync not off in config)",
|
|
16053
|
+
false
|
|
16054
|
+
).option(
|
|
16055
|
+
"--git-data",
|
|
16056
|
+
"legacy no-op: default sync already updates the data branch via git only",
|
|
16057
|
+
false
|
|
16058
|
+
).option(
|
|
16059
|
+
"--skip-push",
|
|
16060
|
+
"after a successful sync, do not push the data branch to the remote",
|
|
16061
|
+
false
|
|
16062
|
+
).action(async function() {
|
|
15533
16063
|
const g = readGlobals(this);
|
|
15534
16064
|
const o = this.opts();
|
|
15535
16065
|
const repoRoot = await resolveRepoRoot(g.repo);
|
|
15536
16066
|
const cfg = await loadMergedConfig(repoRoot, g);
|
|
15537
|
-
if (
|
|
16067
|
+
if (o.withGithub && o.skipNetwork) {
|
|
16068
|
+
deps.error("Cannot use --with-github together with --skip-network");
|
|
16069
|
+
deps.exit(ExitCode.UserError);
|
|
16070
|
+
}
|
|
16071
|
+
if (o.skipNetwork) {
|
|
15538
16072
|
deps.log(formatOutput(g.format, { ok: true, skipped: true }));
|
|
15539
16073
|
deps.exit(ExitCode.Success);
|
|
15540
16074
|
}
|
|
15541
|
-
|
|
15542
|
-
|
|
15543
|
-
|
|
15544
|
-
|
|
15545
|
-
|
|
15546
|
-
|
|
15547
|
-
|
|
15548
|
-
|
|
15549
|
-
|
|
16075
|
+
if (o.withGithub) {
|
|
16076
|
+
if (cfg.sync === "off") {
|
|
16077
|
+
deps.error(
|
|
16078
|
+
"GitHub Issues sync is off in config (sync: off). Omit --with-github to sync the data branch via git only, or set sync to outbound/full."
|
|
16079
|
+
);
|
|
16080
|
+
deps.exit(ExitCode.UserError);
|
|
16081
|
+
}
|
|
16082
|
+
const githubToken = await resolveGithubTokenForSync({
|
|
16083
|
+
envToken: env.GITHUB_TOKEN,
|
|
16084
|
+
cwd: repoRoot
|
|
16085
|
+
});
|
|
16086
|
+
if (!githubToken) {
|
|
16087
|
+
deps.error(
|
|
16088
|
+
"GitHub auth required for sync --with-github: set GITHUB_TOKEN or run `gh auth login`"
|
|
16089
|
+
);
|
|
16090
|
+
deps.exit(ExitCode.EnvironmentAuth);
|
|
16091
|
+
}
|
|
16092
|
+
const tmpBase = g.tempDir ?? env.TMPDIR ?? (0, import_node_os2.tmpdir)();
|
|
16093
|
+
const session = await openDataBranchWorktree({
|
|
16094
|
+
repoRoot,
|
|
16095
|
+
dataBranch: cfg.dataBranch,
|
|
16096
|
+
tmpBase,
|
|
16097
|
+
keepWorktree: g.keepWorktree,
|
|
16098
|
+
runGit
|
|
16099
|
+
});
|
|
16100
|
+
try {
|
|
16101
|
+
const projection = await loadProjectionFromDataRoot(
|
|
16102
|
+
session.worktreePath
|
|
16103
|
+
);
|
|
16104
|
+
const gitDerivedSlug = await tryReadGithubOwnerRepoSlugFromGit({
|
|
16105
|
+
repoRoot,
|
|
16106
|
+
remote: cfg.remote,
|
|
16107
|
+
runGit
|
|
16108
|
+
});
|
|
16109
|
+
const { owner, repo: repo2 } = resolveGithubRepo(
|
|
16110
|
+
cfg,
|
|
16111
|
+
env.GITHUB_REPO,
|
|
16112
|
+
gitDerivedSlug
|
|
16113
|
+
);
|
|
16114
|
+
const octokit = new Octokit2({ auth: githubToken });
|
|
16115
|
+
const outboundActor = await resolveGithubTokenActor(octokit);
|
|
16116
|
+
const depsGh = {
|
|
16117
|
+
octokit,
|
|
16118
|
+
owner,
|
|
16119
|
+
repo: repo2,
|
|
16120
|
+
clock: deps.clock,
|
|
16121
|
+
outboundActor
|
|
16122
|
+
};
|
|
16123
|
+
await runGithubOutboundSync({
|
|
16124
|
+
dataRoot: session.worktreePath,
|
|
16125
|
+
projection,
|
|
16126
|
+
config: cfg,
|
|
16127
|
+
deps: depsGh
|
|
16128
|
+
});
|
|
16129
|
+
await runGithubInboundSync({
|
|
16130
|
+
dataRoot: session.worktreePath,
|
|
16131
|
+
projection,
|
|
16132
|
+
config: cfg,
|
|
16133
|
+
deps: depsGh
|
|
16134
|
+
});
|
|
16135
|
+
const projectionAfterInbound = await loadProjectionFromDataRoot(
|
|
16136
|
+
session.worktreePath
|
|
16137
|
+
);
|
|
16138
|
+
await runGithubPrActivitySync({
|
|
16139
|
+
projection: projectionAfterInbound,
|
|
16140
|
+
config: cfg,
|
|
16141
|
+
deps: defaultGithubPrActivitySyncDeps({
|
|
16142
|
+
dataRoot: session.worktreePath,
|
|
16143
|
+
clock: deps.clock,
|
|
16144
|
+
octokit,
|
|
16145
|
+
owner,
|
|
16146
|
+
repo: repo2,
|
|
16147
|
+
actor: outboundActor
|
|
16148
|
+
})
|
|
16149
|
+
});
|
|
16150
|
+
await commitDataWorktreeIfNeeded(
|
|
16151
|
+
session.worktreePath,
|
|
16152
|
+
formatDataBranchCommitMessage("hyper-pm: sync", outboundActor),
|
|
16153
|
+
runGit
|
|
16154
|
+
);
|
|
16155
|
+
let dataBranchPush;
|
|
16156
|
+
let dataBranchPushDetail;
|
|
16157
|
+
if (o.skipPush) {
|
|
16158
|
+
dataBranchPush = "skipped_cli";
|
|
16159
|
+
dataBranchPushDetail = "skip-push";
|
|
16160
|
+
} else {
|
|
16161
|
+
const pushResult = await tryPushDataBranchToRemote(
|
|
16162
|
+
session.worktreePath,
|
|
16163
|
+
cfg.remote,
|
|
16164
|
+
cfg.dataBranch,
|
|
16165
|
+
runGit
|
|
16166
|
+
);
|
|
16167
|
+
dataBranchPush = pushResult.status;
|
|
16168
|
+
dataBranchPushDetail = pushResult.detail;
|
|
16169
|
+
if (pushResult.status === "failed" && pushResult.detail) {
|
|
16170
|
+
deps.error(
|
|
16171
|
+
`hyper-pm: data branch not pushed (${cfg.remote}/${cfg.dataBranch}): ${pushResult.detail}`
|
|
16172
|
+
);
|
|
16173
|
+
}
|
|
16174
|
+
}
|
|
16175
|
+
deps.log(
|
|
16176
|
+
formatOutput(g.format, {
|
|
16177
|
+
ok: true,
|
|
16178
|
+
githubSync: true,
|
|
16179
|
+
dataBranchPush,
|
|
16180
|
+
...dataBranchPushDetail !== void 0 ? { dataBranchPushDetail } : {}
|
|
16181
|
+
})
|
|
16182
|
+
);
|
|
16183
|
+
} catch (e) {
|
|
16184
|
+
deps.error(e instanceof Error ? e.message : String(e));
|
|
16185
|
+
deps.exit(ExitCode.ExternalApi);
|
|
16186
|
+
} finally {
|
|
16187
|
+
await session.dispose();
|
|
16188
|
+
}
|
|
16189
|
+
deps.exit(ExitCode.Success);
|
|
15550
16190
|
}
|
|
15551
|
-
const
|
|
15552
|
-
const
|
|
16191
|
+
const tmpBaseGit = g.tempDir ?? env.TMPDIR ?? (0, import_node_os2.tmpdir)();
|
|
16192
|
+
const sessionGit = await openDataBranchWorktree({
|
|
15553
16193
|
repoRoot,
|
|
15554
16194
|
dataBranch: cfg.dataBranch,
|
|
15555
|
-
tmpBase,
|
|
16195
|
+
tmpBase: tmpBaseGit,
|
|
15556
16196
|
keepWorktree: g.keepWorktree,
|
|
15557
16197
|
runGit
|
|
15558
16198
|
});
|
|
15559
16199
|
try {
|
|
15560
|
-
|
|
15561
|
-
|
|
15562
|
-
|
|
15563
|
-
|
|
15564
|
-
|
|
15565
|
-
|
|
15566
|
-
|
|
15567
|
-
|
|
15568
|
-
|
|
15569
|
-
|
|
15570
|
-
|
|
15571
|
-
|
|
15572
|
-
|
|
15573
|
-
|
|
15574
|
-
|
|
15575
|
-
|
|
15576
|
-
|
|
15577
|
-
|
|
15578
|
-
|
|
15579
|
-
|
|
15580
|
-
|
|
15581
|
-
}
|
|
15582
|
-
|
|
15583
|
-
|
|
15584
|
-
|
|
15585
|
-
|
|
15586
|
-
|
|
15587
|
-
|
|
15588
|
-
await runGithubInboundSync({
|
|
15589
|
-
dataRoot: session.worktreePath,
|
|
15590
|
-
projection,
|
|
15591
|
-
config: cfg,
|
|
15592
|
-
deps: depsGh
|
|
15593
|
-
});
|
|
15594
|
-
const projectionAfterInbound = await loadProjectionFromDataRoot(
|
|
15595
|
-
session.worktreePath
|
|
15596
|
-
);
|
|
15597
|
-
await runGithubPrActivitySync({
|
|
15598
|
-
projection: projectionAfterInbound,
|
|
15599
|
-
config: cfg,
|
|
15600
|
-
deps: defaultGithubPrActivitySyncDeps({
|
|
15601
|
-
dataRoot: session.worktreePath,
|
|
15602
|
-
clock: deps.clock,
|
|
15603
|
-
octokit,
|
|
15604
|
-
owner,
|
|
15605
|
-
repo: repo2,
|
|
15606
|
-
actor: outboundActor
|
|
16200
|
+
let syncResult;
|
|
16201
|
+
try {
|
|
16202
|
+
syncResult = await runRemoteDataBranchGitSync(
|
|
16203
|
+
sessionGit.worktreePath,
|
|
16204
|
+
cfg.remote,
|
|
16205
|
+
cfg.dataBranch,
|
|
16206
|
+
runGit,
|
|
16207
|
+
Boolean(o.skipPush)
|
|
16208
|
+
);
|
|
16209
|
+
} catch (e) {
|
|
16210
|
+
if (e instanceof SyncRemoteDataBranchMergeError) {
|
|
16211
|
+
deps.error(e.message);
|
|
16212
|
+
deps.exit(ExitCode.UserError);
|
|
16213
|
+
}
|
|
16214
|
+
deps.error(e instanceof Error ? e.message : String(e));
|
|
16215
|
+
deps.exit(ExitCode.UserError);
|
|
16216
|
+
}
|
|
16217
|
+
if (syncResult.dataBranchPush === "failed" && syncResult.dataBranchPushDetail !== void 0) {
|
|
16218
|
+
deps.error(
|
|
16219
|
+
`hyper-pm: data branch not pushed (${cfg.remote}/${cfg.dataBranch}): ${syncResult.dataBranchPushDetail}`
|
|
16220
|
+
);
|
|
16221
|
+
}
|
|
16222
|
+
deps.log(
|
|
16223
|
+
formatOutput(g.format, {
|
|
16224
|
+
ok: true,
|
|
16225
|
+
gitDataOnly: true,
|
|
16226
|
+
...o.gitData ? { legacyGitDataFlag: true } : {},
|
|
16227
|
+
...syncResult
|
|
15607
16228
|
})
|
|
15608
|
-
});
|
|
15609
|
-
await commitDataWorktreeIfNeeded(
|
|
15610
|
-
session.worktreePath,
|
|
15611
|
-
formatDataBranchCommitMessage("hyper-pm: sync", outboundActor),
|
|
15612
|
-
runGit
|
|
15613
16229
|
);
|
|
15614
|
-
deps.log(formatOutput(g.format, { ok: true }));
|
|
15615
|
-
} catch (e) {
|
|
15616
|
-
deps.error(e instanceof Error ? e.message : String(e));
|
|
15617
|
-
deps.exit(ExitCode.ExternalApi);
|
|
15618
16230
|
} finally {
|
|
15619
|
-
await
|
|
16231
|
+
await sessionGit.dispose();
|
|
15620
16232
|
}
|
|
15621
16233
|
deps.exit(ExitCode.Success);
|
|
15622
16234
|
});
|
|
@@ -15782,7 +16394,7 @@ ${body}`
|
|
|
15782
16394
|
await session.dispose();
|
|
15783
16395
|
}
|
|
15784
16396
|
});
|
|
15785
|
-
await program2.parseAsync(argv, { from: "node" });
|
|
16397
|
+
await program2.parseAsync(normalizeRawCliArgv(argv), { from: "node" });
|
|
15786
16398
|
};
|
|
15787
16399
|
var makeEvent = (type, payload, clock, actor) => ({
|
|
15788
16400
|
schema: 1,
|