@autoclawd/autoclawd 1.1.6 → 1.1.7

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/dist/index.js CHANGED
@@ -31,7 +31,8 @@ var LinearConfigSchema = z.object({
31
31
  statuses: z.array(z.string()).default(["Todo"]),
32
32
  assignToMe: z.boolean().default(true),
33
33
  doneStatus: z.string().default("Done"),
34
- inProgressStatus: z.string().default("In Progress")
34
+ inProgressStatus: z.string().default("In Progress"),
35
+ inReviewStatus: z.string().default("In Review")
35
36
  });
36
37
  var GitHubConfigSchema = z.object({
37
38
  token: z.string(),
@@ -328,6 +329,20 @@ async function fetchTicket(client, identifier) {
328
329
  url: issue.url
329
330
  };
330
331
  }
332
+ async function fetchTicketStatus(client, identifier) {
333
+ const match = identifier.match(/^([A-Za-z]+)-(\d+)$/);
334
+ if (!match) return void 0;
335
+ const [, teamKey, numStr] = match;
336
+ const team = await client.team(teamKey.toUpperCase());
337
+ const result = await team.issues({
338
+ filter: { number: { eq: parseInt(numStr) } },
339
+ first: 1
340
+ });
341
+ const issue = result.nodes[0];
342
+ if (!issue) return void 0;
343
+ const state = await issue.state;
344
+ return state?.name;
345
+ }
331
346
  async function claimTicket(client, config, ticketId) {
332
347
  log.info(`Claiming ticket, moving to "${config.linear.inProgressStatus}"`);
333
348
  await retry(async () => {
@@ -342,17 +357,23 @@ async function claimTicket(client, config, ticketId) {
342
357
  await client.updateIssue(ticketId, { stateId: inProgress.id });
343
358
  }, { label: "Linear claim", retryIf: isTransientError });
344
359
  }
345
- async function completeTicket(client, config, ticketId, comment) {
360
+ async function reviewTicket(client, config, ticketId, comment) {
346
361
  await retry(async () => {
347
362
  await client.createComment({ issueId: ticketId, body: comment });
348
363
  const team = await client.team(config.linear.teamId);
349
364
  const states = await team.states();
350
- const doneTarget = config.linear.doneStatus.toLowerCase();
351
- const done = states.nodes.find((s) => s.name.toLowerCase() === doneTarget);
352
- if (done) {
353
- await client.updateIssue(ticketId, { stateId: done.id });
365
+ const target = config.linear.inReviewStatus.toLowerCase();
366
+ const review = states.nodes.find((s) => s.name.toLowerCase() === target);
367
+ if (review) {
368
+ await client.updateIssue(ticketId, { stateId: review.id });
369
+ } else {
370
+ const doneTarget = config.linear.doneStatus.toLowerCase();
371
+ const done = states.nodes.find((s) => s.name.toLowerCase() === doneTarget);
372
+ if (done) {
373
+ await client.updateIssue(ticketId, { stateId: done.id });
374
+ }
354
375
  }
355
- }, { label: "Linear complete", retryIf: isTransientError });
376
+ }, { label: "Linear review", retryIf: isTransientError });
356
377
  }
357
378
  async function addBranchLabel(client, ticketId, branchName) {
358
379
  try {
@@ -1590,8 +1611,28 @@ async function executeTicket(opts) {
1590
1611
  let workDir;
1591
1612
  let container;
1592
1613
  try {
1593
- await claimTicket(linearClient, config, ticket.id);
1594
- log.ticket(ticket.identifier, `Claimed \u2014 ${ticket.repoUrl}`);
1614
+ if (ticket.baseBranch) {
1615
+ const parentMatch = ticket.baseBranch.match(/^autoclawd\/([A-Z]+-\d+)/i);
1616
+ if (parentMatch) {
1617
+ const parentId = parentMatch[1].toUpperCase();
1618
+ const parentStatus = await fetchTicketStatus(linearClient, parentId);
1619
+ if (parentStatus) {
1620
+ const statusLower = parentStatus.toLowerCase();
1621
+ const reviewTarget = config.linear.inReviewStatus.toLowerCase();
1622
+ const doneTarget = config.linear.doneStatus.toLowerCase();
1623
+ if (statusLower !== reviewTarget && statusLower !== doneTarget) {
1624
+ log.ticket(ticket.identifier, `Parent ${parentId} is "${parentStatus}" \u2014 waiting for "${config.linear.inReviewStatus}" or "${config.linear.doneStatus}"`);
1625
+ return {
1626
+ ticketId: ticket.identifier,
1627
+ success: false,
1628
+ error: `REQUEUE: parent ${parentId} is "${parentStatus}", not yet in review or done`,
1629
+ iterations: 0
1630
+ };
1631
+ }
1632
+ log.ticket(ticket.identifier, `Parent ${parentId} is "${parentStatus}" \u2014 proceeding`);
1633
+ }
1634
+ }
1635
+ }
1595
1636
  const { owner: repoOwner, repo: repoName } = parseRepoUrl(ticket.repoUrl);
1596
1637
  const { created: repoCreated } = await ensureRepoExists(octokit, {
1597
1638
  owner: repoOwner,
@@ -1653,6 +1694,8 @@ async function executeTicket(opts) {
1653
1694
  }
1654
1695
  }
1655
1696
  execSync3(`git checkout -B ${branchName} --`, { cwd: workDir, stdio: "pipe" });
1697
+ await claimTicket(linearClient, config, ticket.id);
1698
+ log.ticket(ticket.identifier, `Claimed \u2014 ${ticket.repoUrl}`);
1656
1699
  container = await createContainer({
1657
1700
  dockerConfig: docker2,
1658
1701
  workspacePath: workDir,
@@ -1792,7 +1835,7 @@ async function executeTicket(opts) {
1792
1835
  }
1793
1836
  }
1794
1837
  }
1795
- await completeTicket(linearClient, config, ticket.id, `PR opened: ${pr.url}`);
1838
+ await reviewTicket(linearClient, config, ticket.id, `PR opened: ${pr.url}`);
1796
1839
  await addBranchLabel(linearClient, ticket.id, branchName);
1797
1840
  log.success(`${ticket.identifier} done \u2014 ${pr.url}`);
1798
1841
  const result = {