@henryqw/pi-pr 2.1.1 → 2.1.2

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 CHANGED
@@ -41,8 +41,8 @@ Each footer entry is one linked `PR #number` plus one plain-language status: `N
41
41
  | --- | --- |
42
42
  | No current-branch pull request, including no upstream push target | Start pull-request creation. |
43
43
  | Base update required or merge conflict | Update from the base branch's current target when the tree is clean and local HEAD equals the PR head. |
44
- | Changes requested or unresolved review threads | Run the package comment sweep when the same local prerequisite holds. |
45
44
  | CI failed | Run the CI fix workflow when the same local prerequisite holds. |
45
+ | Changes requested or unresolved review threads | Run the package comment sweep when the same local prerequisite holds. |
46
46
  | No-action state | Report the state without taking action. |
47
47
  | Merge-ready pull request | Ask for final confirmation, recheck fresh state, and merge directly if confirmed. |
48
48
 
@@ -68,8 +68,8 @@ A missing pull request uses creation. For an existing pull request, the first ma
68
68
 
69
69
  1. Merged, closed, or draft: no action.
70
70
  2. Base update required or merge conflict. Run only with a clean tree and equal local and PR heads.
71
- 3. Changes requested or unresolved review threads. Apply the same local prerequisite.
72
- 4. CI failure. Apply the same local prerequisite.
71
+ 3. CI failure. Apply the same local prerequisite.
72
+ 4. Changes requested or unresolved review threads. Apply the same local prerequisite.
73
73
  5. Waiting or local safety block: no action.
74
74
  6. Merge-ready: allow clean local HEAD equal to or behind the PR head. Confirm, then merge directly.
75
75
 
@@ -78,9 +78,9 @@
78
78
  <line x1="704" y1="360" x2="704" y2="392" stroke="rgba(16,24,40,0.141)" stroke-width="1"/>
79
79
  <text x="148" y="384" fill="#4c5665" font-size="12" font-family="'Geist Mono', monospace" text-anchor="middle">4</text>
80
80
  <text x="200" y="368" fill="#4c5665" font-size="8" font-weight="500" font-family="'Geist Mono', monospace" letter-spacing="0.12em">CONDITION</text>
81
- <text x="200" y="388" fill="#101828" font-size="12" font-weight="600" font-family="'Geist', sans-serif">Changes requested or unresolved threads</text>
81
+ <text x="200" y="388" fill="#101828" font-size="12" font-weight="600" font-family="'Geist', sans-serif">CI failed</text>
82
82
  <text x="728" y="368" fill="#4c5665" font-size="8" font-weight="500" font-family="'Geist Mono', monospace" letter-spacing="0.12em">ROUTE</text>
83
- <text x="728" y="388" fill="#101828" font-size="12" font-weight="600" font-family="'Geist', sans-serif">Sweep if clean + equal</text>
83
+ <text x="728" y="388" fill="#101828" font-size="12" font-weight="600" font-family="'Geist', sans-serif">Fix CI if clean + equal</text>
84
84
  <text x="1136" y="388" fill="#4c5665" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">otherwise no action</text>
85
85
 
86
86
  <!-- 5 -->
@@ -89,9 +89,9 @@
89
89
  <line x1="704" y1="424" x2="704" y2="456" stroke="rgba(16,24,40,0.141)" stroke-width="1"/>
90
90
  <text x="148" y="448" fill="#4c5665" font-size="12" font-family="'Geist Mono', monospace" text-anchor="middle">5</text>
91
91
  <text x="200" y="432" fill="#4c5665" font-size="8" font-weight="500" font-family="'Geist Mono', monospace" letter-spacing="0.12em">CONDITION</text>
92
- <text x="200" y="452" fill="#101828" font-size="12" font-weight="600" font-family="'Geist', sans-serif">CI failed</text>
92
+ <text x="200" y="452" fill="#101828" font-size="12" font-weight="600" font-family="'Geist', sans-serif">Changes requested or unresolved threads</text>
93
93
  <text x="728" y="432" fill="#4c5665" font-size="8" font-weight="500" font-family="'Geist Mono', monospace" letter-spacing="0.12em">ROUTE</text>
94
- <text x="728" y="452" fill="#101828" font-size="12" font-weight="600" font-family="'Geist', sans-serif">Fix CI if clean + equal</text>
94
+ <text x="728" y="452" fill="#101828" font-size="12" font-weight="600" font-family="'Geist', sans-serif">Sweep if clean + equal</text>
95
95
  <text x="1136" y="452" fill="#4c5665" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">otherwise no action</text>
96
96
 
97
97
  <!-- 6 -->
@@ -45,10 +45,10 @@ export function deriveNextStep(pullRequest: PullRequest | null): NextStep {
45
45
  if (conditions.baseUpdateRequired || conditions.conflict) {
46
46
  return localMutationSafe(local) ? "update-branch" : "none";
47
47
  }
48
+ if (conditions.ci === "failure") return localMutationSafe(local) ? "fix-ci" : "none";
48
49
  if (conditions.changesRequested || conditions.unresolvedThreads > 0) {
49
50
  return localMutationSafe(local) ? "sweep" : "none";
50
51
  }
51
- if (conditions.ci === "failure") return localMutationSafe(local) ? "fix-ci" : "none";
52
52
  if (
53
53
  conditions.ci === "running" ||
54
54
  conditions.review === "pending" ||
@@ -38,9 +38,9 @@ function footerStatus(input: PrDisplayInput, nextStep: NextStep): Pick<PrFooter,
38
38
  if (conditions.draft) return { text: "draft", color: "warning" };
39
39
  if (conditions.conflict) return { text: "merge conflict", color: "error" };
40
40
  if (conditions.baseUpdateRequired) return { text: "base update required", color: "warning" };
41
+ if (conditions.ci === "failure") return { text: "CI failed", color: "error" };
41
42
  if (conditions.unresolvedThreads > 0) return { text: `${conditions.unresolvedThreads} unresolved`, color: "warning" };
42
43
  if (conditions.changesRequested) return { text: "changes requested", color: "error" };
43
- if (conditions.ci === "failure") return { text: "CI failed", color: "error" };
44
44
  if (conditions.ci === "running") return { text: "CI running", color: "warning" };
45
45
  if (nextStep === "merge") return { text: "merge-ready", color: "success" };
46
46
  if (input.approved) return { text: "approved", color: "success" };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@henryqw/pi-pr",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "description": "Run /pr to automatically choose the current pull request's next safe lifecycle step: create, update, address feedback, fix CI, or merge when ready.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -36,4 +36,23 @@ Create current branch GitHub pull request.
36
36
  Reuse one result only when its base matches. Refresh its title and body.
37
37
  Stop on a different base or multiple results. Otherwise create with explicit
38
38
  `--head <OWNER>:<ref>`, `--base <base>`, title, and body file.
39
- 6. Reply only with PR URL.
39
+ 6. After successful create or reuse, retain the already validated PR URL. Parse
40
+ its PR path segment with Node's standard `URL` and derive `<number>`. Require
41
+ the positive decimal form `^[1-9][0-9]*$`.
42
+
43
+ Only when `HERDR_ENV=1` and trimmed `HERDR_WORKSPACE_ID` is non-empty, use
44
+ that trimmed value as `<workspace-id>`. Run `herdr workspace get
45
+ "<workspace-id>"`. Parse its default JSON with Node's standard library
46
+ (`node:fs` and `JSON.parse`), not `jq`. Require
47
+ `result.workspace.workspace_id` to exactly equal `<workspace-id>` and
48
+ `result.workspace.label` to be a non-empty string.
49
+ Remove every trailing suffix with `/(?: · PR #[1-9][0-9]*)+$/` from the
50
+ label, then append exactly one ` · PR #<number>` suffix. Run `herdr workspace
51
+ rename "<workspace-id>" "<normalized-label>"` only when the normalized label
52
+ differs from the current label. Rename only the workspace, never a pane, tab,
53
+ Pi session, or Git branch.
54
+
55
+ Otherwise, including outside Herdr, skip labeling silently. If any
56
+ workspace-label step fails after PR success, do not undo the PR; reply with
57
+ its URL and `Herdr workspace rename failed: <error>`. Otherwise reply only
58
+ with the PR URL.