atris 3.82.25 → 3.82.26

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.
@@ -201,6 +201,23 @@ function shipHelp() {
201
201
  console.log(' recommended flight verify: npm run test:fast && node --test <focused files>');
202
202
  }
203
203
 
204
+ // A pull request GitHub left open for its checks goes on the list the autoland
205
+ // tick watches. A flaky merge-line run that drops it is then queued again
206
+ // without a person. Failing to write the list never fails the ship.
207
+ function recordPendingShip(root, { branch, targetRef, number }) {
208
+ try {
209
+ const pushed = runGit(['rev-parse', 'HEAD'], { cwd: root }).stdout.trim();
210
+ const autoland = require('../lib/member-autoland');
211
+ autoland.recordQueuedPullRequest(root, { branch, base: baseBranchName(targetRef), number, pushed });
212
+ // The tick skips the whole list while self-landing is off.
213
+ console.log(autoland.policyOn(root)
214
+ ? `queue: recorded pull request ${number} for the tick's catch-up`
215
+ : `queue: recorded pull request ${number}, catch-up is off until self-landing is on`);
216
+ } catch (error) {
217
+ console.log(`queue: not recorded (${String(error.message || error).split('\n')[0]})`);
218
+ }
219
+ }
220
+
204
221
  function shipWorktree(args) {
205
222
  if (hasFlag(args, '--help') || hasFlag(args, '-h') || args[0] === 'help') {
206
223
  shipHelp();
@@ -396,6 +413,7 @@ function shipWorktree(args) {
396
413
  }
397
414
  if (state.state === 'OPEN' && !state.mergedAt) {
398
415
  console.log('merge: pending; kept the source branch while required checks finish');
416
+ recordPendingShip(root, { branch, targetRef, number: state.number });
399
417
  finishShippedCopy({ root, primary, branch, keep: keepCopy });
400
418
  return 0;
401
419
  }
@@ -384,14 +384,36 @@ function writeQueue(file, entries) {
384
384
  fs.renameSync(tmp, file);
385
385
  }
386
386
 
387
- function recordQueued(cwd, entry) {
387
+ // Put a pull request on the list the sweep watches, keyed by its branch. Autoland
388
+ // does this when it queues a member's change; `atris worktree ship --merge`
389
+ // does it when GitHub leaves the pull request open for its checks. A flaky
390
+ // merge-line run that drops it is then caught up by the sweep too. A later
391
+ // record for the same branch keeps its catch-up count and retry mark while
392
+ // the pushed commit and pull request stay the same. A new commit starts them
393
+ // over. A new pull request number starts a new entry: the jobs and mission
394
+ // of the earlier pull request do not carry over, or its merge would close
395
+ // jobs it never carried. fresh: true replaces the entry outright. Throws when
396
+ // the details cannot be recorded; the caller decides whether that matters.
397
+ function recordQueuedPullRequest(cwd, fields, { fresh = false } = {}) {
388
398
  const file = queueFile(cwd);
389
- if (!file) return;
390
- try {
391
- const entries = readQueue(file);
392
- entries[entry.branch] = entry;
393
- writeQueue(file, entries);
394
- } catch {}
399
+ if (!file) throw new Error('not inside a git checkout');
400
+ const { branch, base, number, pushed } = fields || {};
401
+ const valid = typeof branch === 'string' && branch && typeof base === 'string' && base
402
+ && Number.isInteger(number) && number > 0 && /^[0-9a-f]{40,64}$/.test(String(pushed || ''));
403
+ if (!valid) throw new Error('the branch, base, pull request number, or pushed commit could not be read');
404
+ const entries = readQueue(file);
405
+ const found = fresh ? null : entries[branch];
406
+ const prior = found && typeof found === 'object' && found.number === number ? found : null;
407
+ const same = Boolean(prior) && prior.pushed === pushed;
408
+ const entry = { ...(prior || {}), ...fields };
409
+ if (!fresh) {
410
+ entry.requeues = same ? Number(prior.requeues) || 0 : 0;
411
+ entry.reran = same ? prior.reran || false : false;
412
+ }
413
+ entry.queued_at = new Date().toISOString();
414
+ entries[branch] = entry;
415
+ writeQueue(file, entries);
416
+ return entry;
395
417
  }
396
418
 
397
419
  function held(gate, line) {
@@ -566,12 +588,14 @@ function autolandMemberRun({ mission, cwd, summary = '', workerEngine = '', load
566
588
 
567
589
  const merge = run('gh', ['pr', 'merge', String(number), '--auto', '--merge', '--match-head-commit', pushSha], cwd);
568
590
  if (!merge.ok) return held('auto-merge', `auto-merge could not be switched on for ${label}`);
569
- recordQueued(cwd, {
570
- branch, base, number, pushed: pushSha, mission_id: mission.id || null,
571
- task_ids: [...new Set([...taskIds, ...(Array.isArray(closeTaskIds) ? closeTaskIds : [])
572
- .filter((id) => typeof id === 'string' && id.trim()).map((id) => id.trim())])],
573
- requeues: 0, queued_at: new Date().toISOString(),
574
- });
591
+ try {
592
+ recordQueuedPullRequest(cwd, {
593
+ branch, base, number, pushed: pushSha, mission_id: mission.id || null,
594
+ task_ids: [...new Set([...taskIds, ...(Array.isArray(closeTaskIds) ? closeTaskIds : [])
595
+ .filter((id) => typeof id === 'string' && id.trim()).map((id) => id.trim())])],
596
+ requeues: 0,
597
+ }, { fresh: true });
598
+ } catch {}
575
599
  const mapNote = landing.mapInboxed?.length ? ' (map edits saved to the map inbox)'
576
600
  : landing.mapMerged ? ' (map lines from both sides kept)' : '';
577
601
  return {
@@ -931,6 +955,8 @@ module.exports = {
931
955
  sweepAfterMissionRun,
932
956
  landingDestination,
933
957
  requeueDroppedAutolands,
958
+ recordQueuedPullRequest,
959
+ policyOn,
934
960
  codeStatus,
935
961
  gitCodeState,
936
962
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atris",
3
- "version": "3.82.25",
3
+ "version": "3.82.26",
4
4
  "description": "you say what you want in plain words. atris builds it, checks it, and shows you proof. project memory your coding agents share across sessions.",
5
5
  "mcpName": "io.github.atrislabs/atris",
6
6
  "main": "bin/atris.js",