@on-par/factory-cli 0.9.5-next.10 → 0.9.5-next.12

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.
@@ -0,0 +1,298 @@
1
+ // packages/cli/src/cli/land.ts — issue-level land flow: resolve the PR, honor the merge gate, land it (#2784)
2
+ import { existsSync } from 'node:fs';
3
+ import { phaseSnapshotFile, resolveMergePolicy, resolveSandboxPolicy, touchRunActivity } from '@on-par/factory-core';
4
+ import { branchFor, factoryBranchPrefixes, getIssueTitle, isAutoMergeBlocked, LEGACY_BRANCH_PREFIX, logEvent, resolveEffectiveConfig, resolveFilingPolicy, withFileLock, withGitLock, worktreeSandboxFor, } from '@on-par/factory-core/internal';
5
+ import { AwaitingReviewError, CiFailedError, LandConflictError, LandFailureError, MergeGatedError, landOpenPullRequest, } from './land-pr.js';
6
+ import { landRuntime } from './land-runtime.js';
7
+ export async function landIssue(issueNum, repoRoot, ghRepo, paths, octokit, skipCI, branchPrefix, opts = {}) {
8
+ const { configLoaders, gitOps, errorDetail, worktreePathFor } = landRuntime();
9
+ const [owner, repoName] = ghRepo.split('/');
10
+ const log = (type, msg, extra) => logEvent(paths.events, type, issueNum, msg, extra);
11
+ // The issue title may have been edited since the PR was opened, so a
12
+ // freshly-derived branch name can drift from the branch the PR actually
13
+ // lives on (same failure mode fixed for waitForMerge in #51). Guess the
14
+ // branch from the current title first, but fall back to matching the open
15
+ // PR that references this issue directly and use its real head branch.
16
+ // Legacy-prefix (LEGACY_BRANCH_PREFIX) branches are guessed too, after the resolved prefix (#1708).
17
+ const resolved = branchPrefix ?? resolveEffectiveConfig(configLoaders.loadRepoConfig(repoRoot)).branchPrefix;
18
+ const title = await getIssueTitle(ghRepo, issueNum, octokit);
19
+ // ADR-0161: a stack layer lands by its exact branch, never by title guess or the Closes PR (the top layer).
20
+ const guesses = opts.branch
21
+ ? [opts.branch]
22
+ : factoryBranchPrefixes(resolved).map((p) => branchFor(issueNum, title, p));
23
+ const guessedBranch = guesses[0];
24
+ let branch = guessedBranch;
25
+ let prNumber;
26
+ try {
27
+ const findByGuess = async () => {
28
+ for (const guess of guesses) {
29
+ const found = await findOpenPRNumber(octokit, owner, repoName, guess);
30
+ if (found) {
31
+ branch = guess;
32
+ return found;
33
+ }
34
+ }
35
+ return undefined;
36
+ };
37
+ [, prNumber] = await Promise.all([gitOps.gitFetch(repoRoot), findByGuess()]);
38
+ if (!prNumber && !opts.branch) {
39
+ const fallback = await findOpenPRForIssue(octokit, owner, repoName, issueNum);
40
+ if (fallback) {
41
+ branch = fallback.branch;
42
+ prNumber = fallback.number;
43
+ }
44
+ }
45
+ }
46
+ catch (err) {
47
+ const failure = prLookupFailure(issueNum, guessedBranch, err);
48
+ log('fail', failure.message);
49
+ throw failure;
50
+ }
51
+ if (!prNumber) {
52
+ log('fail', `no open PR for ${guessedBranch}`);
53
+ throw new LandFailureError(`no open PR for issue #${issueNum} (${guessedBranch})`, 1);
54
+ }
55
+ const landFactoryConfig = configLoaders.loadFactoryConfigForRepo(paths.config);
56
+ // Every merge path honors the no-auto-merge gate on the issue and on the PR; unreadable labels fail closed (#1720).
57
+ const filingPolicy = resolveFilingPolicy(landFactoryConfig);
58
+ const gateLabel = filingPolicy.selfFixLabel;
59
+ if (opts.allowGated) {
60
+ console.log(`AUDIT factory land #${issueNum}: --allow-gated override — merging PR #${prNumber} past the ${gateLabel} gate`);
61
+ log('merge-gated-override', `--allow-gated: merging PR #${prNumber} past ${gateLabel} gate (human override)`);
62
+ }
63
+ else {
64
+ let where;
65
+ try {
66
+ const [issueLabels, prLabels] = await Promise.all([
67
+ defaultListIssueLabels(octokit, owner, repoName, issueNum),
68
+ defaultListIssueLabels(octokit, owner, repoName, prNumber),
69
+ ]);
70
+ if (isAutoMergeBlocked(issueLabels, filingPolicy))
71
+ where = `issue #${issueNum} is labelled ${gateLabel}`;
72
+ else if (isAutoMergeBlocked(prLabels, filingPolicy))
73
+ where = `PR #${prNumber} is labelled ${gateLabel}`;
74
+ }
75
+ catch (err) {
76
+ where = `labels could not be read (${errorDetail(err)}) — failing closed on the ${gateLabel} gate`;
77
+ }
78
+ if (where) {
79
+ log('merge-gated', `land refused: ${where}`);
80
+ throw new MergeGatedError(`not merging PR #${prNumber} for issue #${issueNum}: ${where} (human approval required). Re-run \`factory land ${issueNum} --allow-gated\` to merge it deliberately.`, issueNum, prNumber, gateLabel);
81
+ }
82
+ }
83
+ const worktree = worktreePathFor(repoRoot, ghRepo, issueNum, branch.startsWith(`${LEGACY_BRANCH_PREFIX}/`) ? LEGACY_BRANCH_PREFIX : resolved);
84
+ const landSandboxPolicy = resolveSandboxPolicy(landFactoryConfig.sandbox, {
85
+ worktree,
86
+ repoRoot,
87
+ });
88
+ const worktreeSandbox = worktreeSandboxFor(landSandboxPolicy?.runtime, {
89
+ allowHosts: landSandboxPolicy?.allowHosts ?? [],
90
+ });
91
+ const withLandLock = (fn) => withGitLock(repoRoot, () => withFileLock(paths.mergeLock, fn, {
92
+ onSteal: (pid) => log('lock-stolen', `stole ${paths.mergeLock} from dead holder pid ${pid ?? 'unknown'}`),
93
+ }));
94
+ try {
95
+ try {
96
+ await landOpenPullRequest({
97
+ octokit,
98
+ owner,
99
+ repoName,
100
+ ghRepo,
101
+ repoRoot,
102
+ issue: issueNum,
103
+ branch,
104
+ worktree,
105
+ prNumber: prNumber,
106
+ log,
107
+ skipCI,
108
+ adminMerge: resolveMergePolicy(landFactoryConfig).admin,
109
+ withLock: withLandLock,
110
+ ensureWorktree: async () => {
111
+ if (!existsSync(worktree)) {
112
+ await gitOps.setupWorktree(repoRoot, branch, worktree, `origin/${branch}`, worktreeSandbox, log);
113
+ }
114
+ },
115
+ });
116
+ }
117
+ catch (err) {
118
+ if (err instanceof AwaitingReviewError || err instanceof CiFailedError) {
119
+ await withLandLock(() => gitOps.cleanupWorktree(repoRoot, worktree, log, worktreeSandbox));
120
+ }
121
+ throw err;
122
+ }
123
+ log('merged', `squash-merged PR #${prNumber}`);
124
+ await withLandLock(() => gitOps.cleanupWorktree(repoRoot, worktree, log, worktreeSandbox));
125
+ }
126
+ catch (err) {
127
+ if (err instanceof LandConflictError || err instanceof AwaitingReviewError || err instanceof CiFailedError)
128
+ throw err;
129
+ log('fail', `merge failed: ${err.message}`);
130
+ throw new LandFailureError(`merge failed for issue #${issueNum}: ${err.message}`, 5);
131
+ }
132
+ return { branch, prNumber };
133
+ }
134
+ export function prLookupFailure(issueNum, branch, err) {
135
+ return new LandFailureError(`PR lookup failed for issue #${issueNum} (${branch}): ${landRuntime().errorDetail(err)}`, 5);
136
+ }
137
+ export async function isPrMerged(octokit, owner, repoName, branch) {
138
+ const { data: prs } = await octokit.rest.pulls.list({
139
+ owner,
140
+ repo: repoName,
141
+ state: 'all',
142
+ head: `${owner}:${branch}`,
143
+ });
144
+ if (prs.length === 0)
145
+ return false;
146
+ // Ship-it branch names get reused across separate runs for the same issue
147
+ // (e.g. a "verify-and-close" pass recreates the exact branch name an
148
+ // earlier, already-merged PR used) — GitHub PR numbers only increase, so
149
+ // the highest-numbered PR under this head is always the current one.
150
+ // Checking "was ANY PR ever merged under this branch name" (the old
151
+ // `state: 'closed'` + `.some()` behavior) matched the stale prior PR and
152
+ // falsely reported a brand-new, still-open PR under the same name as
153
+ // merged — waitForMerge then logged "landed" and skipped calling land(),
154
+ // leaving the real PR open forever while the lane believed it was done.
155
+ const latest = prs.reduce((newest, pr) => (pr.number > newest.number ? pr : newest));
156
+ return Boolean(latest.merged_at);
157
+ }
158
+ export async function findOpenPRNumber(octokit, owner, repoName, branch) {
159
+ const { data: prs } = await octokit.rest.pulls.list({
160
+ owner,
161
+ repo: repoName,
162
+ state: 'open',
163
+ head: `${owner}:${branch}`,
164
+ });
165
+ return prs[0]?.number;
166
+ }
167
+ export async function findOpenPRForIssue(octokit, owner, repoName, issueNum) {
168
+ const perPage = 100;
169
+ const matches = new RegExp(`\\bcloses\\s+#${issueNum}\\b`, 'i');
170
+ for (let page = 1;; page++) {
171
+ const { data: prs } = await octokit.rest.pulls.list({
172
+ owner,
173
+ repo: repoName,
174
+ state: 'open',
175
+ per_page: perPage,
176
+ page,
177
+ });
178
+ const pr = prs.find((p) => matches.test(p.body ?? ''));
179
+ if (pr) {
180
+ const headRepoFullName = pr.head.repo?.full_name ?? null;
181
+ if (headRepoFullName !== `${owner}/${repoName}`) {
182
+ return {
183
+ number: pr.number,
184
+ branch: pr.head.ref,
185
+ headSha: pr.head.sha,
186
+ headRepoFullName,
187
+ };
188
+ }
189
+ return { number: pr.number, branch: pr.head.ref, headSha: pr.head.sha, headRepoFullName };
190
+ }
191
+ if (prs.length < perPage)
192
+ return undefined;
193
+ }
194
+ }
195
+ /** Consecutive merged-state check failures tolerated before waitForMerge parks the lane.
196
+ * At the shipped 120s poll that is ~20 minutes of 100% failure (ADR: sustained-failure park). */
197
+ export const MERGE_CHECK_MAX_CONSECUTIVE_FAILURES = 10;
198
+ /** Wall-clock backstop: continuous merged-state check failure for this long parks the lane even
199
+ * if fewer than MERGE_CHECK_MAX_CONSECUTIVE_FAILURES attempts were made (slower poll cadence). */
200
+ export const MERGE_CHECK_FAILURE_BUDGET_MS = 2 * 60 * 60 * 1000;
201
+ /** GitHub signals both primary and secondary rate limits with 403 — the same status it uses for a
202
+ * token that genuinely lacks the scope. Only a 403 with no rate-limit evidence is permanent. */
203
+ function looksRateLimited(err) {
204
+ const headers = err?.response?.headers ?? {};
205
+ const remaining = headers['x-ratelimit-remaining'];
206
+ if (typeof remaining === 'string' && remaining.trim() === '0')
207
+ return true;
208
+ if (typeof remaining === 'number' && remaining === 0)
209
+ return true;
210
+ if (headers['retry-after'] !== undefined)
211
+ return true;
212
+ return /rate limit|secondary rate|abuse detection/i.test(landRuntime().errorDetail(err));
213
+ }
214
+ /** True when a merged-state check failure cannot recover by retrying: an expired/revoked token
215
+ * (401) or a token missing `pulls:read` (403 with no rate-limit evidence). */
216
+ export function isPermanentMergeCheckError(err) {
217
+ const status = err?.status;
218
+ if (status === 401)
219
+ return true;
220
+ if (status !== 403)
221
+ return false;
222
+ return !looksRateLimited(err);
223
+ }
224
+ async function defaultListIssueLabels(octokit, owner, repo, issue) {
225
+ const { data } = await octokit.rest.issues.listLabelsOnIssue({ owner, repo, issue_number: issue });
226
+ return data.map((label) => label.name);
227
+ }
228
+ export async function waitForMerge(issue, branch, repoRoot, ghRepo, paths, deps = {}) {
229
+ const { createOctokit = landRuntime().getOctokit, pathExists = existsSync, checkMerged = isPrMerged, loadConfig = landRuntime().configLoaders.loadFactoryConfigForRepo, land = landIssue, listIssueLabels = defaultListIssueLabels, sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), emitEvent = logEvent, mergeEnabled, writeLine = (line) => console.log(line), now = () => Date.now(), mergeOverrides, landBranch, } = deps;
230
+ const { configLoaders, errorDetail, LaneParkError } = landRuntime();
231
+ const factoryConfig = loadConfig(paths.config);
232
+ const isMergeEnabled = mergeEnabled ?? (() => resolveMergePolicy(factoryConfig, process.env, mergeOverrides).auto);
233
+ const skipCI = configLoaders.resolveSkipCI(factoryConfig);
234
+ const filingPolicy = resolveFilingPolicy(factoryConfig);
235
+ const octokit = createOctokit();
236
+ const [owner, repoName] = ghRepo.split('/');
237
+ emitEvent(paths.events, 'await-merge', issue, `waiting to merge ${branch}`);
238
+ let consecutiveFailures = 0;
239
+ let firstFailureAt = null;
240
+ while (!pathExists(paths.stop)) {
241
+ // The merge wait logs nothing on its happy path, so each poll bumps the per-issue heartbeat:
242
+ // status/TUI staleness rules (ADR-0086, ADR-0093) otherwise read a live wait as a dead run.
243
+ if (paths.runs)
244
+ touchRunActivity(phaseSnapshotFile(paths.runs, issue), new Date().toISOString()).catch(() => { });
245
+ let merged = false;
246
+ try {
247
+ merged = await checkMerged(octokit, owner, repoName, branch);
248
+ consecutiveFailures = 0;
249
+ firstFailureAt = null;
250
+ }
251
+ catch (err) {
252
+ consecutiveFailures++;
253
+ firstFailureAt ??= now();
254
+ const detail = errorDetail(err);
255
+ emitEvent(paths.events, 'warn', issue, `merged-state check failed (treating as not merged): ${detail}`);
256
+ const permanent = isPermanentMergeCheckError(err);
257
+ const elapsedMs = now() - firstFailureAt;
258
+ const budgetSpent = elapsedMs >= MERGE_CHECK_FAILURE_BUDGET_MS;
259
+ const streakSpent = consecutiveFailures >= MERGE_CHECK_MAX_CONSECUTIVE_FAILURES;
260
+ if (permanent || streakSpent || budgetSpent) {
261
+ const trigger = permanent
262
+ ? 'permanent error (auth/scope — retrying cannot help)'
263
+ : `${consecutiveFailures} consecutive failures over ${Math.round(elapsedMs / 1000)}s`;
264
+ const msg = `merged-state check for ${branch} is not recovering — parking lane after ${trigger}: ${detail}`;
265
+ emitEvent(paths.events, 'escalate', issue, msg);
266
+ throw new LaneParkError(msg, 'escalate');
267
+ }
268
+ }
269
+ if (merged) {
270
+ emitEvent(paths.events, 'landed', issue, 'PR merged');
271
+ return;
272
+ }
273
+ if (isMergeEnabled()) {
274
+ let labels = [];
275
+ try {
276
+ labels = await listIssueLabels(octokit, owner, repoName, issue);
277
+ }
278
+ catch (err) {
279
+ emitEvent(paths.events, 'warn', issue, `label check failed (treating as blocked): ${errorDetail(err)}`);
280
+ labels = [filingPolicy.selfFixLabel];
281
+ }
282
+ if (isAutoMergeBlocked(labels, filingPolicy)) {
283
+ emitEvent(paths.events, 'merge-gated', issue, `auto-merge blocked by ${filingPolicy.selfFixLabel} — awaiting human approval`);
284
+ writeLine(`[factory] #${issue} auto-merge gated (${filingPolicy.selfFixLabel}); awaiting human merge (poll 120s)`);
285
+ await sleep(120_000);
286
+ continue;
287
+ }
288
+ if (landBranch)
289
+ await land(issue, repoRoot, ghRepo, paths, octokit, skipCI, undefined, { branch: landBranch });
290
+ else
291
+ await land(issue, repoRoot, ghRepo, paths, octokit, skipCI);
292
+ return;
293
+ }
294
+ writeLine(`[factory] #${issue} awaiting human merge (poll 120s)`);
295
+ await sleep(120_000);
296
+ }
297
+ }
298
+ //# sourceMappingURL=land.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"land.js","sourceRoot":"","sources":["../../src/cli/land.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@on-par/factory-cli",
3
- "version": "0.9.5-next.10",
3
+ "version": "0.9.5-next.12",
4
4
  "description": "On PAR Dev's Software Factory CLI: takes a GitHub issue through plan, build and check with AI agents, then opens a ready-for-review PR.",
5
5
  "keywords": [
6
6
  "ai-agents",
@@ -47,8 +47,8 @@
47
47
  "@octokit/plugin-retry": "^8.1.1",
48
48
  "@octokit/plugin-throttling": "^11.0.5",
49
49
  "@octokit/rest": "^22.0.0",
50
- "@on-par/factory-core": "0.9.5-next.10",
51
- "@on-par/factory-tui": "0.9.5-next.10",
50
+ "@on-par/factory-core": "0.9.5-next.12",
51
+ "@on-par/factory-tui": "0.9.5-next.12",
52
52
  "commander": "^15.0.0"
53
53
  },
54
54
  "license": "MIT",