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/index.cjs
CHANGED
|
@@ -7622,6 +7622,20 @@ var envSchema = external_exports.object({
|
|
|
7622
7622
|
HYPER_PM_AI_API_KEY: external_exports.string().optional(),
|
|
7623
7623
|
/** Optional override for hyper-pm JSONL event `actor` on CLI mutations. */
|
|
7624
7624
|
HYPER_PM_ACTOR: external_exports.string().optional(),
|
|
7625
|
+
/**
|
|
7626
|
+
* Optional `git user.name` for hyper-pm data-branch commits when repo git
|
|
7627
|
+
* identity is unset (falls back after `GIT_AUTHOR_*`, then a built-in default).
|
|
7628
|
+
*/
|
|
7629
|
+
HYPER_PM_GIT_USER_NAME: external_exports.string().optional(),
|
|
7630
|
+
/**
|
|
7631
|
+
* Optional `git user.email` for hyper-pm data-branch commits when repo git
|
|
7632
|
+
* identity is unset (falls back after `GIT_AUTHOR_*`, then a built-in default).
|
|
7633
|
+
*/
|
|
7634
|
+
HYPER_PM_GIT_USER_EMAIL: external_exports.string().optional(),
|
|
7635
|
+
/** Standard Git override for commit author name (optional). */
|
|
7636
|
+
GIT_AUTHOR_NAME: external_exports.string().optional(),
|
|
7637
|
+
/** Standard Git override for commit author email (optional). */
|
|
7638
|
+
GIT_AUTHOR_EMAIL: external_exports.string().optional(),
|
|
7625
7639
|
/**
|
|
7626
7640
|
* Absolute path to the hyper-pm CLI bundle (`main.cjs`) for hyper-pm-mcp and
|
|
7627
7641
|
* other integrations when auto-resolution from the `hyper-pm` package is insufficient.
|
|
@@ -11526,6 +11540,103 @@ var normalizeTicketBranchListFromPayloadValue = (value) => {
|
|
|
11526
11540
|
return normalizeTicketBranchListFromStrings(strings);
|
|
11527
11541
|
};
|
|
11528
11542
|
|
|
11543
|
+
// src/lib/ticket-depends-on.ts
|
|
11544
|
+
var normalizeTicketDependsOnIds = (ids) => {
|
|
11545
|
+
const out = [];
|
|
11546
|
+
const seen = /* @__PURE__ */ new Set();
|
|
11547
|
+
for (const raw of ids) {
|
|
11548
|
+
const t = raw.trim();
|
|
11549
|
+
if (t === "") continue;
|
|
11550
|
+
if (seen.has(t)) continue;
|
|
11551
|
+
seen.add(t);
|
|
11552
|
+
out.push(t);
|
|
11553
|
+
}
|
|
11554
|
+
return out;
|
|
11555
|
+
};
|
|
11556
|
+
var ticketDependsOnListsEqual = (a, b) => {
|
|
11557
|
+
const an = normalizeTicketDependsOnIds(a ?? []);
|
|
11558
|
+
const bn = normalizeTicketDependsOnIds(b ?? []);
|
|
11559
|
+
if (an.length !== bn.length) return false;
|
|
11560
|
+
return an.every((x, i) => x === bn[i]);
|
|
11561
|
+
};
|
|
11562
|
+
var parseTicketDependsOnFromPayloadValue = (value) => {
|
|
11563
|
+
if (!Array.isArray(value)) return void 0;
|
|
11564
|
+
const strings = [];
|
|
11565
|
+
for (const x of value) {
|
|
11566
|
+
if (typeof x !== "string") return void 0;
|
|
11567
|
+
strings.push(x);
|
|
11568
|
+
}
|
|
11569
|
+
return normalizeTicketDependsOnIds(strings);
|
|
11570
|
+
};
|
|
11571
|
+
var parseTicketDependsOnFromFenceValue = (value) => {
|
|
11572
|
+
if (!Array.isArray(value)) return void 0;
|
|
11573
|
+
const strings = [];
|
|
11574
|
+
for (const x of value) {
|
|
11575
|
+
if (typeof x === "string") strings.push(x);
|
|
11576
|
+
}
|
|
11577
|
+
return normalizeTicketDependsOnIds(strings);
|
|
11578
|
+
};
|
|
11579
|
+
var wouldTicketDependsOnCreateCycle = (params) => {
|
|
11580
|
+
const { fromTicketId, nextDependsOn, successorsFor } = params;
|
|
11581
|
+
const dfsFromPrerequisite = (start) => {
|
|
11582
|
+
const stack = [start];
|
|
11583
|
+
const visited = /* @__PURE__ */ new Set();
|
|
11584
|
+
while (stack.length > 0) {
|
|
11585
|
+
const node = stack.pop();
|
|
11586
|
+
if (node === fromTicketId) return true;
|
|
11587
|
+
if (visited.has(node)) continue;
|
|
11588
|
+
visited.add(node);
|
|
11589
|
+
const next = successorsFor(node) ?? [];
|
|
11590
|
+
for (let i = next.length - 1; i >= 0; i -= 1) {
|
|
11591
|
+
stack.push(next[i]);
|
|
11592
|
+
}
|
|
11593
|
+
}
|
|
11594
|
+
return false;
|
|
11595
|
+
};
|
|
11596
|
+
for (const p of nextDependsOn) {
|
|
11597
|
+
if (dfsFromPrerequisite(p)) return true;
|
|
11598
|
+
}
|
|
11599
|
+
return false;
|
|
11600
|
+
};
|
|
11601
|
+
var ticketDependsOnSuccessorsForProjection = (projection, fromTicketId, nextDependsOn) => {
|
|
11602
|
+
return (ticketId) => {
|
|
11603
|
+
if (ticketId === fromTicketId) {
|
|
11604
|
+
return nextDependsOn.length > 0 ? nextDependsOn : void 0;
|
|
11605
|
+
}
|
|
11606
|
+
const row = projection.tickets.get(ticketId);
|
|
11607
|
+
if (!row || row.deleted) return void 0;
|
|
11608
|
+
return row.dependsOn;
|
|
11609
|
+
};
|
|
11610
|
+
};
|
|
11611
|
+
var validateTicketDependsOnForWrite = (params) => {
|
|
11612
|
+
const { projection, fromTicketId, nextDependsOn } = params;
|
|
11613
|
+
for (const id of nextDependsOn) {
|
|
11614
|
+
if (id === fromTicketId) {
|
|
11615
|
+
return `Ticket cannot depend on itself (${id})`;
|
|
11616
|
+
}
|
|
11617
|
+
const row = projection.tickets.get(id);
|
|
11618
|
+
if (row === void 0) {
|
|
11619
|
+
return `Dependency ticket not found: ${id}`;
|
|
11620
|
+
}
|
|
11621
|
+
if (row.deleted) {
|
|
11622
|
+
return `Dependency ticket deleted: ${id}`;
|
|
11623
|
+
}
|
|
11624
|
+
}
|
|
11625
|
+
const successorsFor = ticketDependsOnSuccessorsForProjection(
|
|
11626
|
+
projection,
|
|
11627
|
+
fromTicketId,
|
|
11628
|
+
nextDependsOn
|
|
11629
|
+
);
|
|
11630
|
+
if (wouldTicketDependsOnCreateCycle({
|
|
11631
|
+
fromTicketId,
|
|
11632
|
+
nextDependsOn,
|
|
11633
|
+
successorsFor
|
|
11634
|
+
})) {
|
|
11635
|
+
return "Ticket dependencies would create a cycle";
|
|
11636
|
+
}
|
|
11637
|
+
return void 0;
|
|
11638
|
+
};
|
|
11639
|
+
|
|
11529
11640
|
// src/lib/ticket-planning-fields.ts
|
|
11530
11641
|
var PRIORITY_SET = /* @__PURE__ */ new Set([
|
|
11531
11642
|
"low",
|
|
@@ -11694,6 +11805,9 @@ var formatOutput = (format, value) => {
|
|
|
11694
11805
|
return JSON.stringify(value);
|
|
11695
11806
|
};
|
|
11696
11807
|
|
|
11808
|
+
// src/cli/normalize-raw-cli-argv.ts
|
|
11809
|
+
var normalizeRawCliArgv = (argv) => argv.map((token) => token === "--no-github" ? "--skip-network" : token);
|
|
11810
|
+
|
|
11697
11811
|
// src/cli/prune-unchanged-work-item-update-payload.ts
|
|
11698
11812
|
var branchListsEqual = (a, b) => a.length === b.length && a.every((x, i) => x === b[i]);
|
|
11699
11813
|
var pruneEpicOrStoryUpdatePayloadAgainstRow = (cur, draft) => {
|
|
@@ -11749,6 +11863,20 @@ var pruneTicketUpdatePayloadAgainstRow = (cur, draft) => {
|
|
|
11749
11863
|
out["labels"] = draft["labels"];
|
|
11750
11864
|
}
|
|
11751
11865
|
}
|
|
11866
|
+
if (draft["dependsOn"] !== void 0) {
|
|
11867
|
+
if (draft["dependsOn"] === null) {
|
|
11868
|
+
if (!ticketDependsOnListsEqual(cur.dependsOn, [])) {
|
|
11869
|
+
out["dependsOn"] = null;
|
|
11870
|
+
}
|
|
11871
|
+
} else {
|
|
11872
|
+
const parsed = parseTicketDependsOnFromPayloadValue(draft["dependsOn"]);
|
|
11873
|
+
if (parsed !== void 0) {
|
|
11874
|
+
if (!ticketDependsOnListsEqual(cur.dependsOn, parsed)) {
|
|
11875
|
+
out["dependsOn"] = parsed;
|
|
11876
|
+
}
|
|
11877
|
+
}
|
|
11878
|
+
}
|
|
11879
|
+
}
|
|
11752
11880
|
if (draft["priority"] !== void 0) {
|
|
11753
11881
|
const curP = cur.priority ?? null;
|
|
11754
11882
|
const nextP = draft["priority"] === null ? null : draft["priority"];
|
|
@@ -11915,6 +12043,20 @@ var workItemUpdateAspects = (kind, payload) => {
|
|
|
11915
12043
|
}
|
|
11916
12044
|
}
|
|
11917
12045
|
}
|
|
12046
|
+
if (kind === "ticket" && payload["dependsOn"] !== void 0) {
|
|
12047
|
+
if (payload["dependsOn"] === null) {
|
|
12048
|
+
aspects.push("cleared ticket dependencies");
|
|
12049
|
+
} else {
|
|
12050
|
+
const d = normalizeBranchList(payload["dependsOn"]);
|
|
12051
|
+
if (d.length > 0 && d.length <= MAX_BRANCH_NAMES_TO_LIST) {
|
|
12052
|
+
aspects.push(`set ticket dependencies to (${d.join(", ")})`);
|
|
12053
|
+
} else if (d.length > MAX_BRANCH_NAMES_TO_LIST) {
|
|
12054
|
+
aspects.push("updated ticket dependencies");
|
|
12055
|
+
} else {
|
|
12056
|
+
aspects.push("cleared ticket dependencies");
|
|
12057
|
+
}
|
|
12058
|
+
}
|
|
12059
|
+
}
|
|
11918
12060
|
if (kind === "ticket" && payload["priority"] !== void 0) {
|
|
11919
12061
|
if (payload["priority"] === null) {
|
|
11920
12062
|
aspects.push("cleared priority");
|
|
@@ -12021,6 +12163,7 @@ var buildAuditLinkMetadata = (evt, githubRepo) => {
|
|
|
12021
12163
|
if (p["status"] !== void 0) meta["status"] = String(p["status"]);
|
|
12022
12164
|
if (p["assignee"] !== void 0) meta["assignee"] = p["assignee"];
|
|
12023
12165
|
if (p["labels"] !== void 0) meta["labels"] = p["labels"];
|
|
12166
|
+
if (p["dependsOn"] !== void 0) meta["dependsOn"] = p["dependsOn"];
|
|
12024
12167
|
if (p["priority"] !== void 0) meta["priority"] = p["priority"];
|
|
12025
12168
|
if (p["size"] !== void 0) meta["size"] = p["size"];
|
|
12026
12169
|
if (p["estimate"] !== void 0) meta["estimate"] = p["estimate"];
|
|
@@ -12088,6 +12231,14 @@ var formatEpicStoryTicketCreated = (evt, entity) => {
|
|
|
12088
12231
|
parts.push("with labels");
|
|
12089
12232
|
}
|
|
12090
12233
|
}
|
|
12234
|
+
if (p["dependsOn"] !== void 0) {
|
|
12235
|
+
const d = normalizeBranchList(p["dependsOn"]);
|
|
12236
|
+
if (d.length > 0 && d.length <= MAX_BRANCH_NAMES_TO_LIST) {
|
|
12237
|
+
parts.push(`depending on (${d.join(", ")})`);
|
|
12238
|
+
} else if (d.length > MAX_BRANCH_NAMES_TO_LIST) {
|
|
12239
|
+
parts.push("with ticket dependencies");
|
|
12240
|
+
}
|
|
12241
|
+
}
|
|
12091
12242
|
if (p["priority"] !== void 0) {
|
|
12092
12243
|
parts.push(`with priority ${quoteStatus(String(p["priority"]))}`);
|
|
12093
12244
|
}
|
|
@@ -12181,6 +12332,18 @@ var formatAuditHumanSentence = (evt) => {
|
|
|
12181
12332
|
bits.push("updated labels");
|
|
12182
12333
|
}
|
|
12183
12334
|
}
|
|
12335
|
+
if (p["dependsOn"] !== void 0) {
|
|
12336
|
+
if (p["dependsOn"] === null) {
|
|
12337
|
+
bits.push("cleared ticket dependencies");
|
|
12338
|
+
} else {
|
|
12339
|
+
const d = normalizeBranchList(p["dependsOn"]);
|
|
12340
|
+
if (d.length > 0 && d.length <= MAX_BRANCH_NAMES_TO_LIST) {
|
|
12341
|
+
bits.push(`dependencies: ${d.join(", ")}`);
|
|
12342
|
+
} else {
|
|
12343
|
+
bits.push("updated ticket dependencies");
|
|
12344
|
+
}
|
|
12345
|
+
}
|
|
12346
|
+
}
|
|
12184
12347
|
if (p["priority"] !== void 0) {
|
|
12185
12348
|
bits.push("updated priority");
|
|
12186
12349
|
}
|
|
@@ -12460,6 +12623,13 @@ var ticketMatchesTicketListQuery = (ticket, projection, query) => {
|
|
|
12460
12623
|
return false;
|
|
12461
12624
|
}
|
|
12462
12625
|
}
|
|
12626
|
+
const dependsOnIncludesId = query.dependsOnIncludesId;
|
|
12627
|
+
if (dependsOnIncludesId !== void 0) {
|
|
12628
|
+
const deps = ticket.dependsOn ?? [];
|
|
12629
|
+
if (!deps.includes(dependsOnIncludesId)) {
|
|
12630
|
+
return false;
|
|
12631
|
+
}
|
|
12632
|
+
}
|
|
12463
12633
|
return true;
|
|
12464
12634
|
};
|
|
12465
12635
|
|
|
@@ -12665,6 +12835,7 @@ var listActiveTicketSummaries = (projection, options) => {
|
|
|
12665
12835
|
...t.estimate !== void 0 ? { estimate: t.estimate } : {},
|
|
12666
12836
|
...t.startWorkAt !== void 0 ? { startWorkAt: t.startWorkAt } : {},
|
|
12667
12837
|
...t.targetFinishAt !== void 0 ? { targetFinishAt: t.targetFinishAt } : {},
|
|
12838
|
+
...t.dependsOn !== void 0 && t.dependsOn.length > 0 ? { dependsOn: t.dependsOn } : {},
|
|
12668
12839
|
...t.linkedBranches.length > 0 ? { linkedBranches: t.linkedBranches } : {},
|
|
12669
12840
|
...last !== void 0 ? {
|
|
12670
12841
|
lastPrActivity: {
|
|
@@ -12761,6 +12932,17 @@ var inboundTicketPlanningPayloadFromFenceMeta = (meta) => {
|
|
|
12761
12932
|
}
|
|
12762
12933
|
}
|
|
12763
12934
|
}
|
|
12935
|
+
if (Object.prototype.hasOwnProperty.call(meta, "depends_on")) {
|
|
12936
|
+
const v = meta["depends_on"];
|
|
12937
|
+
if (v === null) {
|
|
12938
|
+
out["dependsOn"] = null;
|
|
12939
|
+
} else {
|
|
12940
|
+
const parsed = parseTicketDependsOnFromFenceValue(v);
|
|
12941
|
+
if (parsed !== void 0) {
|
|
12942
|
+
out["dependsOn"] = parsed;
|
|
12943
|
+
}
|
|
12944
|
+
}
|
|
12945
|
+
}
|
|
12764
12946
|
return out;
|
|
12765
12947
|
};
|
|
12766
12948
|
var buildGithubIssueBody = (params) => {
|
|
@@ -12786,6 +12968,9 @@ var buildGithubIssueBody = (params) => {
|
|
|
12786
12968
|
if (p.targetFinishAt !== void 0) {
|
|
12787
12969
|
meta.target_finish_at = p.targetFinishAt;
|
|
12788
12970
|
}
|
|
12971
|
+
if (p.dependsOn !== void 0 && p.dependsOn.length > 0) {
|
|
12972
|
+
meta.depends_on = p.dependsOn;
|
|
12973
|
+
}
|
|
12789
12974
|
}
|
|
12790
12975
|
return `${params.description.trim()}
|
|
12791
12976
|
|
|
@@ -12811,6 +12996,9 @@ var ticketPlanningForGithubIssueBody = (ticket) => {
|
|
|
12811
12996
|
if (ticket.targetFinishAt !== void 0) {
|
|
12812
12997
|
out.targetFinishAt = ticket.targetFinishAt;
|
|
12813
12998
|
}
|
|
12999
|
+
if (ticket.dependsOn !== void 0 && ticket.dependsOn.length > 0) {
|
|
13000
|
+
out.dependsOn = ticket.dependsOn;
|
|
13001
|
+
}
|
|
12814
13002
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
12815
13003
|
};
|
|
12816
13004
|
|
|
@@ -13363,6 +13551,33 @@ var tryReadGithubOwnerRepoSlugFromGit = async (params) => {
|
|
|
13363
13551
|
}
|
|
13364
13552
|
};
|
|
13365
13553
|
|
|
13554
|
+
// src/git/resolve-effective-git-author-for-data-commit.ts
|
|
13555
|
+
var defaultDataCommitName = "hyper-pm";
|
|
13556
|
+
var defaultDataCommitEmail = "hyper-pm@users.noreply.github.com";
|
|
13557
|
+
var tryReadGitConfigUserName = async (cwd, runGit2) => {
|
|
13558
|
+
try {
|
|
13559
|
+
const { stdout } = await runGit2(cwd, ["config", "--get", "user.name"]);
|
|
13560
|
+
return stdout.trim();
|
|
13561
|
+
} catch {
|
|
13562
|
+
return "";
|
|
13563
|
+
}
|
|
13564
|
+
};
|
|
13565
|
+
var tryReadGitConfigUserEmail = async (cwd, runGit2) => {
|
|
13566
|
+
try {
|
|
13567
|
+
const { stdout } = await runGit2(cwd, ["config", "--get", "user.email"]);
|
|
13568
|
+
return stdout.trim();
|
|
13569
|
+
} catch {
|
|
13570
|
+
return "";
|
|
13571
|
+
}
|
|
13572
|
+
};
|
|
13573
|
+
var resolveEffectiveGitAuthorForDataCommit = async (cwd, runGit2, authorEnv) => {
|
|
13574
|
+
const fromGitName = await tryReadGitConfigUserName(cwd, runGit2);
|
|
13575
|
+
const fromGitEmail = await tryReadGitConfigUserEmail(cwd, runGit2);
|
|
13576
|
+
const name = fromGitName || authorEnv.HYPER_PM_GIT_USER_NAME?.trim() || authorEnv.GIT_AUTHOR_NAME?.trim() || defaultDataCommitName;
|
|
13577
|
+
const email = fromGitEmail || authorEnv.HYPER_PM_GIT_USER_EMAIL?.trim() || authorEnv.GIT_AUTHOR_EMAIL?.trim() || defaultDataCommitEmail;
|
|
13578
|
+
return { name, email };
|
|
13579
|
+
};
|
|
13580
|
+
|
|
13366
13581
|
// src/run/commit-data.ts
|
|
13367
13582
|
var maxActorSuffixLen = 60;
|
|
13368
13583
|
var formatDataBranchCommitMessage = (base, actorSuffix) => {
|
|
@@ -13374,11 +13589,205 @@ var formatDataBranchCommitMessage = (base, actorSuffix) => {
|
|
|
13374
13589
|
const suffix = collapsed.length > maxActorSuffixLen ? `${collapsed.slice(0, maxActorSuffixLen - 1)}\u2026` : collapsed;
|
|
13375
13590
|
return `${base} (${suffix})`;
|
|
13376
13591
|
};
|
|
13377
|
-
var commitDataWorktreeIfNeeded = async (worktreePath, message, runGit2) => {
|
|
13592
|
+
var commitDataWorktreeIfNeeded = async (worktreePath, message, runGit2, opts) => {
|
|
13378
13593
|
const { stdout } = await runGit2(worktreePath, ["status", "--porcelain"]);
|
|
13379
13594
|
if (!stdout.trim()) return;
|
|
13380
13595
|
await runGit2(worktreePath, ["add", "."]);
|
|
13381
|
-
|
|
13596
|
+
const authorEnv = opts?.authorEnv ?? env;
|
|
13597
|
+
const { name, email } = await resolveEffectiveGitAuthorForDataCommit(
|
|
13598
|
+
worktreePath,
|
|
13599
|
+
runGit2,
|
|
13600
|
+
authorEnv
|
|
13601
|
+
);
|
|
13602
|
+
await runGit2(worktreePath, [
|
|
13603
|
+
"-c",
|
|
13604
|
+
`user.name=${name}`,
|
|
13605
|
+
"-c",
|
|
13606
|
+
`user.email=${email}`,
|
|
13607
|
+
"commit",
|
|
13608
|
+
"-m",
|
|
13609
|
+
message
|
|
13610
|
+
]);
|
|
13611
|
+
};
|
|
13612
|
+
|
|
13613
|
+
// src/run/push-data-branch.ts
|
|
13614
|
+
var firstLineFromUnknown = (err) => {
|
|
13615
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
13616
|
+
const line = raw.trim().split("\n")[0]?.trim() ?? raw.trim();
|
|
13617
|
+
return line.length > 0 ? line : "git error";
|
|
13618
|
+
};
|
|
13619
|
+
var tryPushDataBranchToRemote = async (worktreePath, remote, branch, runGit2) => {
|
|
13620
|
+
try {
|
|
13621
|
+
await runGit2(worktreePath, ["remote", "get-url", remote]);
|
|
13622
|
+
} catch (e) {
|
|
13623
|
+
return {
|
|
13624
|
+
status: "skipped_no_remote",
|
|
13625
|
+
detail: firstLineFromUnknown(e)
|
|
13626
|
+
};
|
|
13627
|
+
}
|
|
13628
|
+
try {
|
|
13629
|
+
await runGit2(worktreePath, ["push", "-u", remote, branch]);
|
|
13630
|
+
return { status: "pushed" };
|
|
13631
|
+
} catch (e) {
|
|
13632
|
+
return {
|
|
13633
|
+
status: "failed",
|
|
13634
|
+
detail: firstLineFromUnknown(e)
|
|
13635
|
+
};
|
|
13636
|
+
}
|
|
13637
|
+
};
|
|
13638
|
+
|
|
13639
|
+
// src/run/sync-remote-data-branch.ts
|
|
13640
|
+
var SyncRemoteDataBranchMergeError = class extends Error {
|
|
13641
|
+
/** @param message - Human-readable reason (stderr excerpt or generic text). */
|
|
13642
|
+
constructor(message) {
|
|
13643
|
+
super(message);
|
|
13644
|
+
this.name = "SyncRemoteDataBranchMergeError";
|
|
13645
|
+
}
|
|
13646
|
+
};
|
|
13647
|
+
var remoteTrackingRef = (remote, dataBranch) => `refs/remotes/${remote}/${dataBranch}`;
|
|
13648
|
+
var mergeRefSpecifier = (remote, dataBranch) => `${remote}/${dataBranch}`;
|
|
13649
|
+
var isLikelyNonFastForwardPushFailure = (detail) => {
|
|
13650
|
+
if (detail === void 0) return false;
|
|
13651
|
+
const d = detail.toLowerCase();
|
|
13652
|
+
return d.includes("non-fast-forward") || d.includes("failed to push");
|
|
13653
|
+
};
|
|
13654
|
+
var classifyMergeOutput = (combined) => {
|
|
13655
|
+
const c = combined.toLowerCase();
|
|
13656
|
+
if (c.includes("already up to date")) {
|
|
13657
|
+
return "up_to_date";
|
|
13658
|
+
}
|
|
13659
|
+
if (c.includes("fast-forward")) {
|
|
13660
|
+
return "fast_forward";
|
|
13661
|
+
}
|
|
13662
|
+
return "merge_commit";
|
|
13663
|
+
};
|
|
13664
|
+
var refExists = async (cwd, ref, runGit2) => {
|
|
13665
|
+
try {
|
|
13666
|
+
await runGit2(cwd, ["show-ref", "--verify", "--quiet", ref]);
|
|
13667
|
+
return true;
|
|
13668
|
+
} catch {
|
|
13669
|
+
return false;
|
|
13670
|
+
}
|
|
13671
|
+
};
|
|
13672
|
+
var fetchRemoteDataBranch = async (worktreePath, remote, dataBranch, runGit2) => {
|
|
13673
|
+
try {
|
|
13674
|
+
await runGit2(worktreePath, ["remote", "get-url", remote]);
|
|
13675
|
+
} catch {
|
|
13676
|
+
return "skipped_no_remote";
|
|
13677
|
+
}
|
|
13678
|
+
try {
|
|
13679
|
+
await runGit2(worktreePath, ["fetch", remote, dataBranch]);
|
|
13680
|
+
return "ok";
|
|
13681
|
+
} catch (e) {
|
|
13682
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
13683
|
+
if (/couldn't find remote ref|could not find remote ref/i.test(msg)) {
|
|
13684
|
+
return "remote_branch_absent";
|
|
13685
|
+
}
|
|
13686
|
+
throw e;
|
|
13687
|
+
}
|
|
13688
|
+
};
|
|
13689
|
+
var mergeRemoteTrackingIntoHead = async (worktreePath, remote, dataBranch, runGit2, authorEnv = env) => {
|
|
13690
|
+
const spec = mergeRefSpecifier(remote, dataBranch);
|
|
13691
|
+
const { name, email } = await resolveEffectiveGitAuthorForDataCommit(
|
|
13692
|
+
worktreePath,
|
|
13693
|
+
runGit2,
|
|
13694
|
+
authorEnv
|
|
13695
|
+
);
|
|
13696
|
+
try {
|
|
13697
|
+
const { stdout, stderr } = await runGit2(worktreePath, [
|
|
13698
|
+
"-c",
|
|
13699
|
+
`user.name=${name}`,
|
|
13700
|
+
"-c",
|
|
13701
|
+
`user.email=${email}`,
|
|
13702
|
+
"merge",
|
|
13703
|
+
"--no-edit",
|
|
13704
|
+
spec
|
|
13705
|
+
]);
|
|
13706
|
+
return classifyMergeOutput(`${stdout}
|
|
13707
|
+
${stderr}`);
|
|
13708
|
+
} catch (e) {
|
|
13709
|
+
await runGit2(worktreePath, ["merge", "--abort"]).catch(() => {
|
|
13710
|
+
});
|
|
13711
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
13712
|
+
throw new SyncRemoteDataBranchMergeError(
|
|
13713
|
+
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}`
|
|
13714
|
+
);
|
|
13715
|
+
}
|
|
13716
|
+
};
|
|
13717
|
+
var runRemoteDataBranchGitSync = async (worktreePath, remote, dataBranch, runGit2, skipPush, deps = {}) => {
|
|
13718
|
+
const tryPushFn = deps.tryPush ?? tryPushDataBranchToRemote;
|
|
13719
|
+
const maxPushAttempts = deps.maxPushAttempts ?? 3;
|
|
13720
|
+
const authorEnv = deps.authorEnv ?? env;
|
|
13721
|
+
let dataBranchFetch = await fetchRemoteDataBranch(worktreePath, remote, dataBranch, runGit2);
|
|
13722
|
+
let dataBranchMerge = dataBranchFetch === "skipped_no_remote" ? "skipped_no_remote" : dataBranchFetch === "remote_branch_absent" ? "skipped_missing_remote_branch" : "up_to_date";
|
|
13723
|
+
if (dataBranchFetch === "ok") {
|
|
13724
|
+
const tracking = remoteTrackingRef(remote, dataBranch);
|
|
13725
|
+
const exists = await refExists(worktreePath, tracking, runGit2);
|
|
13726
|
+
if (!exists) {
|
|
13727
|
+
dataBranchMerge = "skipped_missing_remote_branch";
|
|
13728
|
+
} else {
|
|
13729
|
+
dataBranchMerge = await mergeRemoteTrackingIntoHead(
|
|
13730
|
+
worktreePath,
|
|
13731
|
+
remote,
|
|
13732
|
+
dataBranch,
|
|
13733
|
+
runGit2,
|
|
13734
|
+
authorEnv
|
|
13735
|
+
);
|
|
13736
|
+
}
|
|
13737
|
+
}
|
|
13738
|
+
if (skipPush) {
|
|
13739
|
+
return {
|
|
13740
|
+
dataBranchFetch,
|
|
13741
|
+
dataBranchMerge,
|
|
13742
|
+
dataBranchPush: "skipped_cli",
|
|
13743
|
+
dataBranchPushDetail: "skip-push",
|
|
13744
|
+
pushAttempts: 0
|
|
13745
|
+
};
|
|
13746
|
+
}
|
|
13747
|
+
let pushAttempts = 0;
|
|
13748
|
+
let lastPush = { status: "skipped_no_remote" };
|
|
13749
|
+
const refetchAndMerge = async () => {
|
|
13750
|
+
dataBranchFetch = await fetchRemoteDataBranch(
|
|
13751
|
+
worktreePath,
|
|
13752
|
+
remote,
|
|
13753
|
+
dataBranch,
|
|
13754
|
+
runGit2
|
|
13755
|
+
);
|
|
13756
|
+
if (dataBranchFetch !== "ok") {
|
|
13757
|
+
return;
|
|
13758
|
+
}
|
|
13759
|
+
const tracking = remoteTrackingRef(remote, dataBranch);
|
|
13760
|
+
const exists = await refExists(worktreePath, tracking, runGit2);
|
|
13761
|
+
if (!exists) {
|
|
13762
|
+
return;
|
|
13763
|
+
}
|
|
13764
|
+
dataBranchMerge = await mergeRemoteTrackingIntoHead(
|
|
13765
|
+
worktreePath,
|
|
13766
|
+
remote,
|
|
13767
|
+
dataBranch,
|
|
13768
|
+
runGit2,
|
|
13769
|
+
authorEnv
|
|
13770
|
+
);
|
|
13771
|
+
};
|
|
13772
|
+
for (let attempt = 1; attempt <= maxPushAttempts; attempt += 1) {
|
|
13773
|
+
pushAttempts = attempt;
|
|
13774
|
+
lastPush = await tryPushFn(worktreePath, remote, dataBranch, runGit2);
|
|
13775
|
+
if (lastPush.status === "pushed" || lastPush.status === "skipped_no_remote") {
|
|
13776
|
+
break;
|
|
13777
|
+
}
|
|
13778
|
+
if (lastPush.status === "failed" && isLikelyNonFastForwardPushFailure(lastPush.detail) && attempt < maxPushAttempts) {
|
|
13779
|
+
await refetchAndMerge();
|
|
13780
|
+
continue;
|
|
13781
|
+
}
|
|
13782
|
+
break;
|
|
13783
|
+
}
|
|
13784
|
+
return {
|
|
13785
|
+
dataBranchFetch,
|
|
13786
|
+
dataBranchMerge,
|
|
13787
|
+
dataBranchPush: lastPush.status,
|
|
13788
|
+
...lastPush.detail !== void 0 ? { dataBranchPushDetail: lastPush.detail } : {},
|
|
13789
|
+
pushAttempts
|
|
13790
|
+
};
|
|
13382
13791
|
};
|
|
13383
13792
|
|
|
13384
13793
|
// src/storage/append-event.ts
|
|
@@ -13576,6 +13985,12 @@ var applyTicketPlanningFieldsFromCreatePayload = (row, payload) => {
|
|
|
13576
13985
|
if (typeof tf === "string") {
|
|
13577
13986
|
row.targetFinishAt = tf;
|
|
13578
13987
|
}
|
|
13988
|
+
if (Object.prototype.hasOwnProperty.call(payload, "dependsOn")) {
|
|
13989
|
+
const v = parseTicketDependsOnFromPayloadValue(payload["dependsOn"]);
|
|
13990
|
+
if (v !== void 0 && v.length > 0) {
|
|
13991
|
+
row.dependsOn = v;
|
|
13992
|
+
}
|
|
13993
|
+
}
|
|
13579
13994
|
};
|
|
13580
13995
|
var applyTicketPlanningFieldsFromUpdatePayload = (row, payload) => {
|
|
13581
13996
|
if (Object.prototype.hasOwnProperty.call(payload, "labels")) {
|
|
@@ -13622,6 +14037,20 @@ var applyTicketPlanningFieldsFromUpdatePayload = (row, payload) => {
|
|
|
13622
14037
|
} else if (typeof tf === "string") {
|
|
13623
14038
|
row.targetFinishAt = tf;
|
|
13624
14039
|
}
|
|
14040
|
+
if (Object.prototype.hasOwnProperty.call(payload, "dependsOn")) {
|
|
14041
|
+
if (payload["dependsOn"] === null) {
|
|
14042
|
+
delete row.dependsOn;
|
|
14043
|
+
} else {
|
|
14044
|
+
const v = parseTicketDependsOnFromPayloadValue(payload["dependsOn"]);
|
|
14045
|
+
if (v !== void 0) {
|
|
14046
|
+
if (v.length === 0) {
|
|
14047
|
+
delete row.dependsOn;
|
|
14048
|
+
} else {
|
|
14049
|
+
row.dependsOn = v;
|
|
14050
|
+
}
|
|
14051
|
+
}
|
|
14052
|
+
}
|
|
14053
|
+
}
|
|
13625
14054
|
};
|
|
13626
14055
|
var applyCreatedAudit = (row, evt) => {
|
|
13627
14056
|
row.createdAt = evt.ts;
|
|
@@ -14248,6 +14677,19 @@ var runGithubInboundSync = async (params) => {
|
|
|
14248
14677
|
const planningSource = inboundTicketPlanningPayloadFromFenceMeta(meta);
|
|
14249
14678
|
const planningPayload = {};
|
|
14250
14679
|
for (const [k, v] of Object.entries(planningSource)) {
|
|
14680
|
+
if (k === "dependsOn") {
|
|
14681
|
+
if (v === null) {
|
|
14682
|
+
if (!ticketDependsOnListsEqual(ticket.dependsOn, [])) {
|
|
14683
|
+
planningPayload["dependsOn"] = null;
|
|
14684
|
+
}
|
|
14685
|
+
} else if (Array.isArray(v)) {
|
|
14686
|
+
const parsed = parseTicketDependsOnFromPayloadValue(v);
|
|
14687
|
+
if (parsed !== void 0 && !ticketDependsOnListsEqual(ticket.dependsOn, parsed)) {
|
|
14688
|
+
planningPayload["dependsOn"] = parsed;
|
|
14689
|
+
}
|
|
14690
|
+
}
|
|
14691
|
+
continue;
|
|
14692
|
+
}
|
|
14251
14693
|
const tk = k;
|
|
14252
14694
|
const cur = ticket[tk];
|
|
14253
14695
|
if (v === null) {
|
|
@@ -14585,6 +15027,9 @@ var buildTicketListQueryFromReadListOpts = (o, deps) => {
|
|
|
14585
15027
|
if (targetFinishBeforeMs !== void 0) {
|
|
14586
15028
|
query.targetFinishBeforeMs = targetFinishBeforeMs;
|
|
14587
15029
|
}
|
|
15030
|
+
if (o.dependsOn !== void 0 && o.dependsOn.trim() !== "") {
|
|
15031
|
+
query.dependsOnIncludesId = o.dependsOn.trim();
|
|
15032
|
+
}
|
|
14588
15033
|
return Object.keys(query).length > 0 ? query : void 0;
|
|
14589
15034
|
};
|
|
14590
15035
|
var runCli = async (argv, deps = {
|
|
@@ -14808,6 +15253,11 @@ var runCli = async (argv, deps = {
|
|
|
14808
15253
|
"planning label (repeatable)",
|
|
14809
15254
|
(value, previous) => [...previous, value],
|
|
14810
15255
|
[]
|
|
15256
|
+
).option(
|
|
15257
|
+
"--depends-on <id>",
|
|
15258
|
+
"prerequisite ticket id (repeatable)",
|
|
15259
|
+
(value, previous) => [...previous, value],
|
|
15260
|
+
[]
|
|
14811
15261
|
).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() {
|
|
14812
15262
|
const g = readGlobals(this);
|
|
14813
15263
|
const o = this.opts();
|
|
@@ -14870,6 +15320,10 @@ var runCli = async (argv, deps = {
|
|
|
14870
15320
|
"--target-finish-at",
|
|
14871
15321
|
deps
|
|
14872
15322
|
);
|
|
15323
|
+
const dependsOnTokensCreate = normalizeCliStringList(o.dependsOn);
|
|
15324
|
+
const dependsOnNormCreate = normalizeTicketDependsOnIds(
|
|
15325
|
+
dependsOnTokensCreate
|
|
15326
|
+
);
|
|
14873
15327
|
const planningPayload = {
|
|
14874
15328
|
...labelsPayloadCreate,
|
|
14875
15329
|
...priorityParsed !== void 0 ? { priority: priorityParsed } : {},
|
|
@@ -14896,6 +15350,15 @@ var runCli = async (argv, deps = {
|
|
|
14896
15350
|
const branchTokens = normalizeCliStringList(o.branch);
|
|
14897
15351
|
const branchesNorm = normalizeTicketBranchListFromStrings(branchTokens);
|
|
14898
15352
|
const branchesPayload = branchesNorm.length > 0 ? { branches: branchesNorm } : {};
|
|
15353
|
+
const dependsOnErr = validateTicketDependsOnForWrite({
|
|
15354
|
+
projection: proj,
|
|
15355
|
+
fromTicketId: id,
|
|
15356
|
+
nextDependsOn: dependsOnNormCreate
|
|
15357
|
+
});
|
|
15358
|
+
if (dependsOnErr !== void 0) {
|
|
15359
|
+
throw new Error(dependsOnErr);
|
|
15360
|
+
}
|
|
15361
|
+
const dependsOnPayloadCreate = dependsOnNormCreate.length > 0 ? { dependsOn: dependsOnNormCreate } : {};
|
|
14899
15362
|
const evt = makeEvent(
|
|
14900
15363
|
"TicketCreated",
|
|
14901
15364
|
{
|
|
@@ -14906,6 +15369,7 @@ var runCli = async (argv, deps = {
|
|
|
14906
15369
|
...status !== void 0 ? { status } : {},
|
|
14907
15370
|
...assigneeCreate,
|
|
14908
15371
|
...branchesPayload,
|
|
15372
|
+
...dependsOnPayloadCreate,
|
|
14909
15373
|
...planningPayload
|
|
14910
15374
|
},
|
|
14911
15375
|
deps.clock,
|
|
@@ -14963,6 +15427,9 @@ var runCli = async (argv, deps = {
|
|
|
14963
15427
|
).option(
|
|
14964
15428
|
"--branch <name>",
|
|
14965
15429
|
"when listing (no --id): only tickets linked to this branch (normalized exact match)"
|
|
15430
|
+
).option(
|
|
15431
|
+
"--depends-on <id>",
|
|
15432
|
+
"when listing (no --id): only tickets that list this ticket id in dependsOn"
|
|
14966
15433
|
).option(
|
|
14967
15434
|
"--priority <p>",
|
|
14968
15435
|
"when listing (no --id): OR-set of priorities (repeat flag); low|medium|high|urgent",
|
|
@@ -15042,7 +15509,17 @@ var runCli = async (argv, deps = {
|
|
|
15042
15509
|
"--clear-labels",
|
|
15043
15510
|
"remove all planning labels from the ticket",
|
|
15044
15511
|
false
|
|
15045
|
-
).option(
|
|
15512
|
+
).option(
|
|
15513
|
+
"--add-depends-on <id>",
|
|
15514
|
+
"add a prerequisite ticket id (repeatable)",
|
|
15515
|
+
(value, previous) => [...previous, value],
|
|
15516
|
+
[]
|
|
15517
|
+
).option(
|
|
15518
|
+
"--remove-depends-on <id>",
|
|
15519
|
+
"remove a prerequisite ticket id (repeatable)",
|
|
15520
|
+
(value, previous) => [...previous, value],
|
|
15521
|
+
[]
|
|
15522
|
+
).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() {
|
|
15046
15523
|
const g = readGlobals(this);
|
|
15047
15524
|
const o = this.opts();
|
|
15048
15525
|
let body = o.body;
|
|
@@ -15094,6 +15571,14 @@ ${body}`
|
|
|
15094
15571
|
);
|
|
15095
15572
|
deps.exit(ExitCode.UserError);
|
|
15096
15573
|
}
|
|
15574
|
+
const addDependsOnTokens = normalizeCliStringList(o.addDependsOn);
|
|
15575
|
+
const removeDependsOnTokens = normalizeCliStringList(o.removeDependsOn);
|
|
15576
|
+
if (o.clearDependsOn === true && (addDependsOnTokens.length > 0 || removeDependsOnTokens.length > 0)) {
|
|
15577
|
+
deps.error(
|
|
15578
|
+
"Cannot use --clear-depends-on with --add-depends-on or --remove-depends-on"
|
|
15579
|
+
);
|
|
15580
|
+
deps.exit(ExitCode.UserError);
|
|
15581
|
+
}
|
|
15097
15582
|
const mutual = (clear, set, clearName, setName) => {
|
|
15098
15583
|
if (clear === true && set !== void 0 && set !== "") {
|
|
15099
15584
|
deps.error(`Cannot use ${clearName} and ${setName} together`);
|
|
@@ -15226,6 +15711,35 @@ ${body}`
|
|
|
15226
15711
|
payload["labels"] = nextLabels;
|
|
15227
15712
|
}
|
|
15228
15713
|
}
|
|
15714
|
+
const wantsDependsOnChange = o.clearDependsOn === true || addDependsOnTokens.length > 0 || removeDependsOnTokens.length > 0;
|
|
15715
|
+
if (wantsDependsOnChange) {
|
|
15716
|
+
let nextDepends;
|
|
15717
|
+
if (o.clearDependsOn === true) {
|
|
15718
|
+
nextDepends = [];
|
|
15719
|
+
} else {
|
|
15720
|
+
const removeDepSet = new Set(
|
|
15721
|
+
normalizeTicketDependsOnIds(removeDependsOnTokens)
|
|
15722
|
+
);
|
|
15723
|
+
nextDepends = normalizeTicketDependsOnIds(
|
|
15724
|
+
(curTicket.dependsOn ?? []).filter((d) => !removeDepSet.has(d))
|
|
15725
|
+
);
|
|
15726
|
+
nextDepends = normalizeTicketDependsOnIds([
|
|
15727
|
+
...nextDepends,
|
|
15728
|
+
...addDependsOnTokens
|
|
15729
|
+
]);
|
|
15730
|
+
}
|
|
15731
|
+
const depErr = validateTicketDependsOnForWrite({
|
|
15732
|
+
projection: proj,
|
|
15733
|
+
fromTicketId: o.id,
|
|
15734
|
+
nextDependsOn: nextDepends
|
|
15735
|
+
});
|
|
15736
|
+
if (depErr !== void 0) {
|
|
15737
|
+
throw new Error(depErr);
|
|
15738
|
+
}
|
|
15739
|
+
if (!ticketDependsOnListsEqual(curTicket.dependsOn, nextDepends)) {
|
|
15740
|
+
payload["dependsOn"] = nextDepends;
|
|
15741
|
+
}
|
|
15742
|
+
}
|
|
15229
15743
|
if (priorityUpdate !== void 0) {
|
|
15230
15744
|
payload["priority"] = priorityUpdate;
|
|
15231
15745
|
}
|
|
@@ -15539,94 +16053,192 @@ ${body}`
|
|
|
15539
16053
|
}
|
|
15540
16054
|
deps.exit(ExitCode.Success);
|
|
15541
16055
|
});
|
|
15542
|
-
program2.command("sync").description("GitHub Issues sync").option(
|
|
16056
|
+
program2.command("sync").description("Sync data branch over git; optional GitHub Issues sync").option(
|
|
16057
|
+
"--skip-network",
|
|
16058
|
+
"skip all sync network operations (git fetch/merge/push and GitHub); legacy: --no-github",
|
|
16059
|
+
false
|
|
16060
|
+
).option(
|
|
16061
|
+
"--with-github",
|
|
16062
|
+
"also run GitHub Issues sync (requires GITHUB_TOKEN or gh; needs sync not off in config)",
|
|
16063
|
+
false
|
|
16064
|
+
).option(
|
|
16065
|
+
"--git-data",
|
|
16066
|
+
"legacy no-op: default sync already updates the data branch via git only",
|
|
16067
|
+
false
|
|
16068
|
+
).option(
|
|
16069
|
+
"--skip-push",
|
|
16070
|
+
"after a successful sync, do not push the data branch to the remote",
|
|
16071
|
+
false
|
|
16072
|
+
).action(async function() {
|
|
15543
16073
|
const g = readGlobals(this);
|
|
15544
16074
|
const o = this.opts();
|
|
15545
16075
|
const repoRoot = await resolveRepoRoot(g.repo);
|
|
15546
16076
|
const cfg = await loadMergedConfig(repoRoot, g);
|
|
15547
|
-
if (
|
|
16077
|
+
if (o.withGithub && o.skipNetwork) {
|
|
16078
|
+
deps.error("Cannot use --with-github together with --skip-network");
|
|
16079
|
+
deps.exit(ExitCode.UserError);
|
|
16080
|
+
}
|
|
16081
|
+
if (o.skipNetwork) {
|
|
15548
16082
|
deps.log(formatOutput(g.format, { ok: true, skipped: true }));
|
|
15549
16083
|
deps.exit(ExitCode.Success);
|
|
15550
16084
|
}
|
|
15551
|
-
|
|
15552
|
-
|
|
15553
|
-
|
|
15554
|
-
|
|
15555
|
-
|
|
15556
|
-
|
|
15557
|
-
|
|
15558
|
-
|
|
15559
|
-
|
|
16085
|
+
if (o.withGithub) {
|
|
16086
|
+
if (cfg.sync === "off") {
|
|
16087
|
+
deps.error(
|
|
16088
|
+
"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."
|
|
16089
|
+
);
|
|
16090
|
+
deps.exit(ExitCode.UserError);
|
|
16091
|
+
}
|
|
16092
|
+
const githubToken = await resolveGithubTokenForSync({
|
|
16093
|
+
envToken: env.GITHUB_TOKEN,
|
|
16094
|
+
cwd: repoRoot
|
|
16095
|
+
});
|
|
16096
|
+
if (!githubToken) {
|
|
16097
|
+
deps.error(
|
|
16098
|
+
"GitHub auth required for sync --with-github: set GITHUB_TOKEN or run `gh auth login`"
|
|
16099
|
+
);
|
|
16100
|
+
deps.exit(ExitCode.EnvironmentAuth);
|
|
16101
|
+
}
|
|
16102
|
+
const tmpBase = g.tempDir ?? env.TMPDIR ?? (0, import_node_os2.tmpdir)();
|
|
16103
|
+
const session = await openDataBranchWorktree({
|
|
16104
|
+
repoRoot,
|
|
16105
|
+
dataBranch: cfg.dataBranch,
|
|
16106
|
+
tmpBase,
|
|
16107
|
+
keepWorktree: g.keepWorktree,
|
|
16108
|
+
runGit
|
|
16109
|
+
});
|
|
16110
|
+
try {
|
|
16111
|
+
const projection = await loadProjectionFromDataRoot(
|
|
16112
|
+
session.worktreePath
|
|
16113
|
+
);
|
|
16114
|
+
const gitDerivedSlug = await tryReadGithubOwnerRepoSlugFromGit({
|
|
16115
|
+
repoRoot,
|
|
16116
|
+
remote: cfg.remote,
|
|
16117
|
+
runGit
|
|
16118
|
+
});
|
|
16119
|
+
const { owner, repo: repo2 } = resolveGithubRepo(
|
|
16120
|
+
cfg,
|
|
16121
|
+
env.GITHUB_REPO,
|
|
16122
|
+
gitDerivedSlug
|
|
16123
|
+
);
|
|
16124
|
+
const octokit = new Octokit2({ auth: githubToken });
|
|
16125
|
+
const outboundActor = await resolveGithubTokenActor(octokit);
|
|
16126
|
+
const depsGh = {
|
|
16127
|
+
octokit,
|
|
16128
|
+
owner,
|
|
16129
|
+
repo: repo2,
|
|
16130
|
+
clock: deps.clock,
|
|
16131
|
+
outboundActor
|
|
16132
|
+
};
|
|
16133
|
+
await runGithubOutboundSync({
|
|
16134
|
+
dataRoot: session.worktreePath,
|
|
16135
|
+
projection,
|
|
16136
|
+
config: cfg,
|
|
16137
|
+
deps: depsGh
|
|
16138
|
+
});
|
|
16139
|
+
await runGithubInboundSync({
|
|
16140
|
+
dataRoot: session.worktreePath,
|
|
16141
|
+
projection,
|
|
16142
|
+
config: cfg,
|
|
16143
|
+
deps: depsGh
|
|
16144
|
+
});
|
|
16145
|
+
const projectionAfterInbound = await loadProjectionFromDataRoot(
|
|
16146
|
+
session.worktreePath
|
|
16147
|
+
);
|
|
16148
|
+
await runGithubPrActivitySync({
|
|
16149
|
+
projection: projectionAfterInbound,
|
|
16150
|
+
config: cfg,
|
|
16151
|
+
deps: defaultGithubPrActivitySyncDeps({
|
|
16152
|
+
dataRoot: session.worktreePath,
|
|
16153
|
+
clock: deps.clock,
|
|
16154
|
+
octokit,
|
|
16155
|
+
owner,
|
|
16156
|
+
repo: repo2,
|
|
16157
|
+
actor: outboundActor
|
|
16158
|
+
})
|
|
16159
|
+
});
|
|
16160
|
+
await commitDataWorktreeIfNeeded(
|
|
16161
|
+
session.worktreePath,
|
|
16162
|
+
formatDataBranchCommitMessage("hyper-pm: sync", outboundActor),
|
|
16163
|
+
runGit
|
|
16164
|
+
);
|
|
16165
|
+
let dataBranchPush;
|
|
16166
|
+
let dataBranchPushDetail;
|
|
16167
|
+
if (o.skipPush) {
|
|
16168
|
+
dataBranchPush = "skipped_cli";
|
|
16169
|
+
dataBranchPushDetail = "skip-push";
|
|
16170
|
+
} else {
|
|
16171
|
+
const pushResult = await tryPushDataBranchToRemote(
|
|
16172
|
+
session.worktreePath,
|
|
16173
|
+
cfg.remote,
|
|
16174
|
+
cfg.dataBranch,
|
|
16175
|
+
runGit
|
|
16176
|
+
);
|
|
16177
|
+
dataBranchPush = pushResult.status;
|
|
16178
|
+
dataBranchPushDetail = pushResult.detail;
|
|
16179
|
+
if (pushResult.status === "failed" && pushResult.detail) {
|
|
16180
|
+
deps.error(
|
|
16181
|
+
`hyper-pm: data branch not pushed (${cfg.remote}/${cfg.dataBranch}): ${pushResult.detail}`
|
|
16182
|
+
);
|
|
16183
|
+
}
|
|
16184
|
+
}
|
|
16185
|
+
deps.log(
|
|
16186
|
+
formatOutput(g.format, {
|
|
16187
|
+
ok: true,
|
|
16188
|
+
githubSync: true,
|
|
16189
|
+
dataBranchPush,
|
|
16190
|
+
...dataBranchPushDetail !== void 0 ? { dataBranchPushDetail } : {}
|
|
16191
|
+
})
|
|
16192
|
+
);
|
|
16193
|
+
} catch (e) {
|
|
16194
|
+
deps.error(e instanceof Error ? e.message : String(e));
|
|
16195
|
+
deps.exit(ExitCode.ExternalApi);
|
|
16196
|
+
} finally {
|
|
16197
|
+
await session.dispose();
|
|
16198
|
+
}
|
|
16199
|
+
deps.exit(ExitCode.Success);
|
|
15560
16200
|
}
|
|
15561
|
-
const
|
|
15562
|
-
const
|
|
16201
|
+
const tmpBaseGit = g.tempDir ?? env.TMPDIR ?? (0, import_node_os2.tmpdir)();
|
|
16202
|
+
const sessionGit = await openDataBranchWorktree({
|
|
15563
16203
|
repoRoot,
|
|
15564
16204
|
dataBranch: cfg.dataBranch,
|
|
15565
|
-
tmpBase,
|
|
16205
|
+
tmpBase: tmpBaseGit,
|
|
15566
16206
|
keepWorktree: g.keepWorktree,
|
|
15567
16207
|
runGit
|
|
15568
16208
|
});
|
|
15569
16209
|
try {
|
|
15570
|
-
|
|
15571
|
-
|
|
15572
|
-
|
|
15573
|
-
|
|
15574
|
-
|
|
15575
|
-
|
|
15576
|
-
|
|
15577
|
-
|
|
15578
|
-
|
|
15579
|
-
|
|
15580
|
-
|
|
15581
|
-
|
|
15582
|
-
|
|
15583
|
-
|
|
15584
|
-
|
|
15585
|
-
|
|
15586
|
-
|
|
15587
|
-
|
|
15588
|
-
|
|
15589
|
-
|
|
15590
|
-
|
|
15591
|
-
}
|
|
15592
|
-
|
|
15593
|
-
|
|
15594
|
-
|
|
15595
|
-
|
|
15596
|
-
|
|
15597
|
-
|
|
15598
|
-
await runGithubInboundSync({
|
|
15599
|
-
dataRoot: session.worktreePath,
|
|
15600
|
-
projection,
|
|
15601
|
-
config: cfg,
|
|
15602
|
-
deps: depsGh
|
|
15603
|
-
});
|
|
15604
|
-
const projectionAfterInbound = await loadProjectionFromDataRoot(
|
|
15605
|
-
session.worktreePath
|
|
15606
|
-
);
|
|
15607
|
-
await runGithubPrActivitySync({
|
|
15608
|
-
projection: projectionAfterInbound,
|
|
15609
|
-
config: cfg,
|
|
15610
|
-
deps: defaultGithubPrActivitySyncDeps({
|
|
15611
|
-
dataRoot: session.worktreePath,
|
|
15612
|
-
clock: deps.clock,
|
|
15613
|
-
octokit,
|
|
15614
|
-
owner,
|
|
15615
|
-
repo: repo2,
|
|
15616
|
-
actor: outboundActor
|
|
16210
|
+
let syncResult;
|
|
16211
|
+
try {
|
|
16212
|
+
syncResult = await runRemoteDataBranchGitSync(
|
|
16213
|
+
sessionGit.worktreePath,
|
|
16214
|
+
cfg.remote,
|
|
16215
|
+
cfg.dataBranch,
|
|
16216
|
+
runGit,
|
|
16217
|
+
Boolean(o.skipPush)
|
|
16218
|
+
);
|
|
16219
|
+
} catch (e) {
|
|
16220
|
+
if (e instanceof SyncRemoteDataBranchMergeError) {
|
|
16221
|
+
deps.error(e.message);
|
|
16222
|
+
deps.exit(ExitCode.UserError);
|
|
16223
|
+
}
|
|
16224
|
+
deps.error(e instanceof Error ? e.message : String(e));
|
|
16225
|
+
deps.exit(ExitCode.UserError);
|
|
16226
|
+
}
|
|
16227
|
+
if (syncResult.dataBranchPush === "failed" && syncResult.dataBranchPushDetail !== void 0) {
|
|
16228
|
+
deps.error(
|
|
16229
|
+
`hyper-pm: data branch not pushed (${cfg.remote}/${cfg.dataBranch}): ${syncResult.dataBranchPushDetail}`
|
|
16230
|
+
);
|
|
16231
|
+
}
|
|
16232
|
+
deps.log(
|
|
16233
|
+
formatOutput(g.format, {
|
|
16234
|
+
ok: true,
|
|
16235
|
+
gitDataOnly: true,
|
|
16236
|
+
...o.gitData ? { legacyGitDataFlag: true } : {},
|
|
16237
|
+
...syncResult
|
|
15617
16238
|
})
|
|
15618
|
-
});
|
|
15619
|
-
await commitDataWorktreeIfNeeded(
|
|
15620
|
-
session.worktreePath,
|
|
15621
|
-
formatDataBranchCommitMessage("hyper-pm: sync", outboundActor),
|
|
15622
|
-
runGit
|
|
15623
16239
|
);
|
|
15624
|
-
deps.log(formatOutput(g.format, { ok: true }));
|
|
15625
|
-
} catch (e) {
|
|
15626
|
-
deps.error(e instanceof Error ? e.message : String(e));
|
|
15627
|
-
deps.exit(ExitCode.ExternalApi);
|
|
15628
16240
|
} finally {
|
|
15629
|
-
await
|
|
16241
|
+
await sessionGit.dispose();
|
|
15630
16242
|
}
|
|
15631
16243
|
deps.exit(ExitCode.Success);
|
|
15632
16244
|
});
|
|
@@ -15792,7 +16404,7 @@ ${body}`
|
|
|
15792
16404
|
await session.dispose();
|
|
15793
16405
|
}
|
|
15794
16406
|
});
|
|
15795
|
-
await program2.parseAsync(argv, { from: "node" });
|
|
16407
|
+
await program2.parseAsync(normalizeRawCliArgv(argv), { from: "node" });
|
|
15796
16408
|
};
|
|
15797
16409
|
var makeEvent = (type, payload, clock, actor) => ({
|
|
15798
16410
|
schema: 1,
|