hyper-pm 0.1.3 → 0.1.4
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 +9 -4
- package/dist/index.cjs +115 -4
- package/dist/main.cjs +115 -4
- package/env.example +5 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -93,11 +93,16 @@ GitHub Issues sync (outbound + inbound). **Outbound** sets issue `labels` to `hy
|
|
|
93
93
|
|
|
94
94
|
Skips network work if `sync` is `off` in config, or if you pass `--no-github`.
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
| ------------- | -------------------- | -------------------------------- |
|
|
98
|
-
| `--no-github` | Skip GitHub API sync | sync runs when enabled in config |
|
|
96
|
+
When sync runs, after GitHub API work, **`hyper-pm` commits on the data branch** using `git -c user.name=… -c user.email=… commit` so a missing global `user.name` / `user.email` does not block you. Identity is taken from existing git config in the repo, then optional **`HYPER_PM_GIT_USER_NAME`** / **`HYPER_PM_GIT_USER_EMAIL`** (or standard **`GIT_AUTHOR_NAME`** / **`GIT_AUTHOR_EMAIL`**), then built-in defaults.
|
|
99
97
|
|
|
100
|
-
|
|
98
|
+
It then **attempts** `git push -u` to the configured `remote` (default `origin`). A missing remote or a push error **does not fail the command**: JSON output still has `"ok":true` with **`dataBranchPush`** set to `pushed`, `skipped_no_remote`, `failed`, or (with **`--skip-push`**) `skipped_cli`, and optional **`dataBranchPushDetail`**. Push failures are also written to stderr as a single-line hint. Pass **`--skip-push`** to skip the push attempt entirely.
|
|
99
|
+
|
|
100
|
+
| Option | Description | Default |
|
|
101
|
+
| ------------- | --------------------------------------------- | -------------------------------- |
|
|
102
|
+
| `--no-github` | Skip GitHub API sync | sync runs when enabled in config |
|
|
103
|
+
| `--skip-push` | Skip `git push` of the data branch after sync | `false` (push is attempted) |
|
|
104
|
+
|
|
105
|
+
When sync is not skipped, requires `GITHUB_TOKEN` **or** a local `gh` session (`gh auth token` must succeed). For a successful push you still need a configured remote and credentials that allow `git push` to that remote.
|
|
101
106
|
|
|
102
107
|
### `audit`
|
|
103
108
|
|
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.
|
|
@@ -13363,6 +13377,33 @@ var tryReadGithubOwnerRepoSlugFromGit = async (params) => {
|
|
|
13363
13377
|
}
|
|
13364
13378
|
};
|
|
13365
13379
|
|
|
13380
|
+
// src/git/resolve-effective-git-author-for-data-commit.ts
|
|
13381
|
+
var defaultDataCommitName = "hyper-pm";
|
|
13382
|
+
var defaultDataCommitEmail = "hyper-pm@users.noreply.github.com";
|
|
13383
|
+
var tryReadGitConfigUserName = async (cwd, runGit2) => {
|
|
13384
|
+
try {
|
|
13385
|
+
const { stdout } = await runGit2(cwd, ["config", "--get", "user.name"]);
|
|
13386
|
+
return stdout.trim();
|
|
13387
|
+
} catch {
|
|
13388
|
+
return "";
|
|
13389
|
+
}
|
|
13390
|
+
};
|
|
13391
|
+
var tryReadGitConfigUserEmail = async (cwd, runGit2) => {
|
|
13392
|
+
try {
|
|
13393
|
+
const { stdout } = await runGit2(cwd, ["config", "--get", "user.email"]);
|
|
13394
|
+
return stdout.trim();
|
|
13395
|
+
} catch {
|
|
13396
|
+
return "";
|
|
13397
|
+
}
|
|
13398
|
+
};
|
|
13399
|
+
var resolveEffectiveGitAuthorForDataCommit = async (cwd, runGit2, authorEnv) => {
|
|
13400
|
+
const fromGitName = await tryReadGitConfigUserName(cwd, runGit2);
|
|
13401
|
+
const fromGitEmail = await tryReadGitConfigUserEmail(cwd, runGit2);
|
|
13402
|
+
const name = fromGitName || authorEnv.HYPER_PM_GIT_USER_NAME?.trim() || authorEnv.GIT_AUTHOR_NAME?.trim() || defaultDataCommitName;
|
|
13403
|
+
const email = fromGitEmail || authorEnv.HYPER_PM_GIT_USER_EMAIL?.trim() || authorEnv.GIT_AUTHOR_EMAIL?.trim() || defaultDataCommitEmail;
|
|
13404
|
+
return { name, email };
|
|
13405
|
+
};
|
|
13406
|
+
|
|
13366
13407
|
// src/run/commit-data.ts
|
|
13367
13408
|
var maxActorSuffixLen = 60;
|
|
13368
13409
|
var formatDataBranchCommitMessage = (base, actorSuffix) => {
|
|
@@ -13374,11 +13415,51 @@ var formatDataBranchCommitMessage = (base, actorSuffix) => {
|
|
|
13374
13415
|
const suffix = collapsed.length > maxActorSuffixLen ? `${collapsed.slice(0, maxActorSuffixLen - 1)}\u2026` : collapsed;
|
|
13375
13416
|
return `${base} (${suffix})`;
|
|
13376
13417
|
};
|
|
13377
|
-
var commitDataWorktreeIfNeeded = async (worktreePath, message, runGit2) => {
|
|
13418
|
+
var commitDataWorktreeIfNeeded = async (worktreePath, message, runGit2, opts) => {
|
|
13378
13419
|
const { stdout } = await runGit2(worktreePath, ["status", "--porcelain"]);
|
|
13379
13420
|
if (!stdout.trim()) return;
|
|
13380
13421
|
await runGit2(worktreePath, ["add", "."]);
|
|
13381
|
-
|
|
13422
|
+
const authorEnv = opts?.authorEnv ?? env;
|
|
13423
|
+
const { name, email } = await resolveEffectiveGitAuthorForDataCommit(
|
|
13424
|
+
worktreePath,
|
|
13425
|
+
runGit2,
|
|
13426
|
+
authorEnv
|
|
13427
|
+
);
|
|
13428
|
+
await runGit2(worktreePath, [
|
|
13429
|
+
"-c",
|
|
13430
|
+
`user.name=${name}`,
|
|
13431
|
+
"-c",
|
|
13432
|
+
`user.email=${email}`,
|
|
13433
|
+
"commit",
|
|
13434
|
+
"-m",
|
|
13435
|
+
message
|
|
13436
|
+
]);
|
|
13437
|
+
};
|
|
13438
|
+
|
|
13439
|
+
// src/run/push-data-branch.ts
|
|
13440
|
+
var firstLineFromUnknown = (err) => {
|
|
13441
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
13442
|
+
const line = raw.trim().split("\n")[0]?.trim() ?? raw.trim();
|
|
13443
|
+
return line.length > 0 ? line : "git error";
|
|
13444
|
+
};
|
|
13445
|
+
var tryPushDataBranchToRemote = async (worktreePath, remote, branch, runGit2) => {
|
|
13446
|
+
try {
|
|
13447
|
+
await runGit2(worktreePath, ["remote", "get-url", remote]);
|
|
13448
|
+
} catch (e) {
|
|
13449
|
+
return {
|
|
13450
|
+
status: "skipped_no_remote",
|
|
13451
|
+
detail: firstLineFromUnknown(e)
|
|
13452
|
+
};
|
|
13453
|
+
}
|
|
13454
|
+
try {
|
|
13455
|
+
await runGit2(worktreePath, ["push", "-u", remote, branch]);
|
|
13456
|
+
return { status: "pushed" };
|
|
13457
|
+
} catch (e) {
|
|
13458
|
+
return {
|
|
13459
|
+
status: "failed",
|
|
13460
|
+
detail: firstLineFromUnknown(e)
|
|
13461
|
+
};
|
|
13462
|
+
}
|
|
13382
13463
|
};
|
|
13383
13464
|
|
|
13384
13465
|
// src/storage/append-event.ts
|
|
@@ -15539,7 +15620,11 @@ ${body}`
|
|
|
15539
15620
|
}
|
|
15540
15621
|
deps.exit(ExitCode.Success);
|
|
15541
15622
|
});
|
|
15542
|
-
program2.command("sync").description("GitHub Issues sync").option("--no-github", "skip network sync", false).
|
|
15623
|
+
program2.command("sync").description("GitHub Issues sync").option("--no-github", "skip network sync", false).option(
|
|
15624
|
+
"--skip-push",
|
|
15625
|
+
"after a successful sync, do not push the data branch to the remote",
|
|
15626
|
+
false
|
|
15627
|
+
).action(async function() {
|
|
15543
15628
|
const g = readGlobals(this);
|
|
15544
15629
|
const o = this.opts();
|
|
15545
15630
|
const repoRoot = await resolveRepoRoot(g.repo);
|
|
@@ -15621,7 +15706,33 @@ ${body}`
|
|
|
15621
15706
|
formatDataBranchCommitMessage("hyper-pm: sync", outboundActor),
|
|
15622
15707
|
runGit
|
|
15623
15708
|
);
|
|
15624
|
-
|
|
15709
|
+
let dataBranchPush;
|
|
15710
|
+
let dataBranchPushDetail;
|
|
15711
|
+
if (o.skipPush) {
|
|
15712
|
+
dataBranchPush = "skipped_cli";
|
|
15713
|
+
dataBranchPushDetail = "skip-push";
|
|
15714
|
+
} else {
|
|
15715
|
+
const pushResult = await tryPushDataBranchToRemote(
|
|
15716
|
+
session.worktreePath,
|
|
15717
|
+
cfg.remote,
|
|
15718
|
+
cfg.dataBranch,
|
|
15719
|
+
runGit
|
|
15720
|
+
);
|
|
15721
|
+
dataBranchPush = pushResult.status;
|
|
15722
|
+
dataBranchPushDetail = pushResult.detail;
|
|
15723
|
+
if (pushResult.status === "failed" && pushResult.detail) {
|
|
15724
|
+
deps.error(
|
|
15725
|
+
`hyper-pm: data branch not pushed (${cfg.remote}/${cfg.dataBranch}): ${pushResult.detail}`
|
|
15726
|
+
);
|
|
15727
|
+
}
|
|
15728
|
+
}
|
|
15729
|
+
deps.log(
|
|
15730
|
+
formatOutput(g.format, {
|
|
15731
|
+
ok: true,
|
|
15732
|
+
dataBranchPush,
|
|
15733
|
+
...dataBranchPushDetail !== void 0 ? { dataBranchPushDetail } : {}
|
|
15734
|
+
})
|
|
15735
|
+
);
|
|
15625
15736
|
} catch (e) {
|
|
15626
15737
|
deps.error(e instanceof Error ? e.message : String(e));
|
|
15627
15738
|
deps.exit(ExitCode.ExternalApi);
|
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.
|
|
@@ -13353,6 +13367,33 @@ var tryReadGithubOwnerRepoSlugFromGit = async (params) => {
|
|
|
13353
13367
|
}
|
|
13354
13368
|
};
|
|
13355
13369
|
|
|
13370
|
+
// src/git/resolve-effective-git-author-for-data-commit.ts
|
|
13371
|
+
var defaultDataCommitName = "hyper-pm";
|
|
13372
|
+
var defaultDataCommitEmail = "hyper-pm@users.noreply.github.com";
|
|
13373
|
+
var tryReadGitConfigUserName = async (cwd, runGit2) => {
|
|
13374
|
+
try {
|
|
13375
|
+
const { stdout } = await runGit2(cwd, ["config", "--get", "user.name"]);
|
|
13376
|
+
return stdout.trim();
|
|
13377
|
+
} catch {
|
|
13378
|
+
return "";
|
|
13379
|
+
}
|
|
13380
|
+
};
|
|
13381
|
+
var tryReadGitConfigUserEmail = async (cwd, runGit2) => {
|
|
13382
|
+
try {
|
|
13383
|
+
const { stdout } = await runGit2(cwd, ["config", "--get", "user.email"]);
|
|
13384
|
+
return stdout.trim();
|
|
13385
|
+
} catch {
|
|
13386
|
+
return "";
|
|
13387
|
+
}
|
|
13388
|
+
};
|
|
13389
|
+
var resolveEffectiveGitAuthorForDataCommit = async (cwd, runGit2, authorEnv) => {
|
|
13390
|
+
const fromGitName = await tryReadGitConfigUserName(cwd, runGit2);
|
|
13391
|
+
const fromGitEmail = await tryReadGitConfigUserEmail(cwd, runGit2);
|
|
13392
|
+
const name = fromGitName || authorEnv.HYPER_PM_GIT_USER_NAME?.trim() || authorEnv.GIT_AUTHOR_NAME?.trim() || defaultDataCommitName;
|
|
13393
|
+
const email = fromGitEmail || authorEnv.HYPER_PM_GIT_USER_EMAIL?.trim() || authorEnv.GIT_AUTHOR_EMAIL?.trim() || defaultDataCommitEmail;
|
|
13394
|
+
return { name, email };
|
|
13395
|
+
};
|
|
13396
|
+
|
|
13356
13397
|
// src/run/commit-data.ts
|
|
13357
13398
|
var maxActorSuffixLen = 60;
|
|
13358
13399
|
var formatDataBranchCommitMessage = (base, actorSuffix) => {
|
|
@@ -13364,11 +13405,51 @@ var formatDataBranchCommitMessage = (base, actorSuffix) => {
|
|
|
13364
13405
|
const suffix = collapsed.length > maxActorSuffixLen ? `${collapsed.slice(0, maxActorSuffixLen - 1)}\u2026` : collapsed;
|
|
13365
13406
|
return `${base} (${suffix})`;
|
|
13366
13407
|
};
|
|
13367
|
-
var commitDataWorktreeIfNeeded = async (worktreePath, message, runGit2) => {
|
|
13408
|
+
var commitDataWorktreeIfNeeded = async (worktreePath, message, runGit2, opts) => {
|
|
13368
13409
|
const { stdout } = await runGit2(worktreePath, ["status", "--porcelain"]);
|
|
13369
13410
|
if (!stdout.trim()) return;
|
|
13370
13411
|
await runGit2(worktreePath, ["add", "."]);
|
|
13371
|
-
|
|
13412
|
+
const authorEnv = opts?.authorEnv ?? env;
|
|
13413
|
+
const { name, email } = await resolveEffectiveGitAuthorForDataCommit(
|
|
13414
|
+
worktreePath,
|
|
13415
|
+
runGit2,
|
|
13416
|
+
authorEnv
|
|
13417
|
+
);
|
|
13418
|
+
await runGit2(worktreePath, [
|
|
13419
|
+
"-c",
|
|
13420
|
+
`user.name=${name}`,
|
|
13421
|
+
"-c",
|
|
13422
|
+
`user.email=${email}`,
|
|
13423
|
+
"commit",
|
|
13424
|
+
"-m",
|
|
13425
|
+
message
|
|
13426
|
+
]);
|
|
13427
|
+
};
|
|
13428
|
+
|
|
13429
|
+
// src/run/push-data-branch.ts
|
|
13430
|
+
var firstLineFromUnknown = (err) => {
|
|
13431
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
13432
|
+
const line = raw.trim().split("\n")[0]?.trim() ?? raw.trim();
|
|
13433
|
+
return line.length > 0 ? line : "git error";
|
|
13434
|
+
};
|
|
13435
|
+
var tryPushDataBranchToRemote = async (worktreePath, remote, branch, runGit2) => {
|
|
13436
|
+
try {
|
|
13437
|
+
await runGit2(worktreePath, ["remote", "get-url", remote]);
|
|
13438
|
+
} catch (e) {
|
|
13439
|
+
return {
|
|
13440
|
+
status: "skipped_no_remote",
|
|
13441
|
+
detail: firstLineFromUnknown(e)
|
|
13442
|
+
};
|
|
13443
|
+
}
|
|
13444
|
+
try {
|
|
13445
|
+
await runGit2(worktreePath, ["push", "-u", remote, branch]);
|
|
13446
|
+
return { status: "pushed" };
|
|
13447
|
+
} catch (e) {
|
|
13448
|
+
return {
|
|
13449
|
+
status: "failed",
|
|
13450
|
+
detail: firstLineFromUnknown(e)
|
|
13451
|
+
};
|
|
13452
|
+
}
|
|
13372
13453
|
};
|
|
13373
13454
|
|
|
13374
13455
|
// src/storage/append-event.ts
|
|
@@ -15529,7 +15610,11 @@ ${body}`
|
|
|
15529
15610
|
}
|
|
15530
15611
|
deps.exit(ExitCode.Success);
|
|
15531
15612
|
});
|
|
15532
|
-
program2.command("sync").description("GitHub Issues sync").option("--no-github", "skip network sync", false).
|
|
15613
|
+
program2.command("sync").description("GitHub Issues sync").option("--no-github", "skip network sync", false).option(
|
|
15614
|
+
"--skip-push",
|
|
15615
|
+
"after a successful sync, do not push the data branch to the remote",
|
|
15616
|
+
false
|
|
15617
|
+
).action(async function() {
|
|
15533
15618
|
const g = readGlobals(this);
|
|
15534
15619
|
const o = this.opts();
|
|
15535
15620
|
const repoRoot = await resolveRepoRoot(g.repo);
|
|
@@ -15611,7 +15696,33 @@ ${body}`
|
|
|
15611
15696
|
formatDataBranchCommitMessage("hyper-pm: sync", outboundActor),
|
|
15612
15697
|
runGit
|
|
15613
15698
|
);
|
|
15614
|
-
|
|
15699
|
+
let dataBranchPush;
|
|
15700
|
+
let dataBranchPushDetail;
|
|
15701
|
+
if (o.skipPush) {
|
|
15702
|
+
dataBranchPush = "skipped_cli";
|
|
15703
|
+
dataBranchPushDetail = "skip-push";
|
|
15704
|
+
} else {
|
|
15705
|
+
const pushResult = await tryPushDataBranchToRemote(
|
|
15706
|
+
session.worktreePath,
|
|
15707
|
+
cfg.remote,
|
|
15708
|
+
cfg.dataBranch,
|
|
15709
|
+
runGit
|
|
15710
|
+
);
|
|
15711
|
+
dataBranchPush = pushResult.status;
|
|
15712
|
+
dataBranchPushDetail = pushResult.detail;
|
|
15713
|
+
if (pushResult.status === "failed" && pushResult.detail) {
|
|
15714
|
+
deps.error(
|
|
15715
|
+
`hyper-pm: data branch not pushed (${cfg.remote}/${cfg.dataBranch}): ${pushResult.detail}`
|
|
15716
|
+
);
|
|
15717
|
+
}
|
|
15718
|
+
}
|
|
15719
|
+
deps.log(
|
|
15720
|
+
formatOutput(g.format, {
|
|
15721
|
+
ok: true,
|
|
15722
|
+
dataBranchPush,
|
|
15723
|
+
...dataBranchPushDetail !== void 0 ? { dataBranchPushDetail } : {}
|
|
15724
|
+
})
|
|
15725
|
+
);
|
|
15615
15726
|
} catch (e) {
|
|
15616
15727
|
deps.error(e instanceof Error ? e.message : String(e));
|
|
15617
15728
|
deps.exit(ExitCode.ExternalApi);
|
package/env.example
CHANGED
|
@@ -6,3 +6,8 @@ GITHUB_TOKEN=""
|
|
|
6
6
|
HYPER_PM_AI_API_KEY=""
|
|
7
7
|
# Optional: default audit actor for CLI mutations (overridden by --actor)
|
|
8
8
|
HYPER_PM_ACTOR=""
|
|
9
|
+
# Optional: git author for data-branch commits when user.name / user.email are unset (see README sync)
|
|
10
|
+
HYPER_PM_GIT_USER_NAME=""
|
|
11
|
+
HYPER_PM_GIT_USER_EMAIL=""
|
|
12
|
+
GIT_AUTHOR_NAME=""
|
|
13
|
+
GIT_AUTHOR_EMAIL=""
|