patchrelay 0.36.11 → 0.36.13

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,70 @@
1
+ import { resolveProject } from "../project-resolution.js";
2
+ import { hasCompleteIssueContext, mergeIssueMetadata, } from "./decision-helpers.js";
3
+ export class WebhookContextLoader {
4
+ config;
5
+ linearProvider;
6
+ constructor(config, linearProvider) {
7
+ this.config = config;
8
+ this.linearProvider = linearProvider;
9
+ }
10
+ async load(normalized) {
11
+ if (!normalized.issue) {
12
+ return undefined;
13
+ }
14
+ let project = resolveProject(this.config, normalized.issue);
15
+ let hydrated = normalized;
16
+ if (!project) {
17
+ const routed = await this.tryHydrateProjectRoute(normalized);
18
+ if (!routed) {
19
+ return undefined;
20
+ }
21
+ hydrated = routed.normalized;
22
+ project = routed.project;
23
+ }
24
+ return {
25
+ project,
26
+ normalized: await this.hydrateIssueContext(project.id, hydrated),
27
+ };
28
+ }
29
+ async hydrateIssueContext(projectId, normalized) {
30
+ if (!normalized.issue)
31
+ return normalized;
32
+ if (normalized.triggerEvent !== "agentSessionCreated" && normalized.triggerEvent !== "agentPrompted" && normalized.entityType !== "Issue") {
33
+ return normalized;
34
+ }
35
+ if (normalized.entityType !== "Issue" && hasCompleteIssueContext(normalized.issue))
36
+ return normalized;
37
+ const linear = await this.linearProvider.forProject(projectId);
38
+ if (!linear)
39
+ return normalized;
40
+ try {
41
+ const liveIssue = await linear.getIssue(normalized.issue.id);
42
+ return { ...normalized, issue: mergeIssueMetadata(normalized.issue, liveIssue) };
43
+ }
44
+ catch {
45
+ return normalized;
46
+ }
47
+ }
48
+ async tryHydrateProjectRoute(normalized) {
49
+ if (!normalized.issue)
50
+ return undefined;
51
+ if (normalized.triggerEvent !== "agentSessionCreated" && normalized.triggerEvent !== "agentPrompted")
52
+ return undefined;
53
+ for (const candidate of this.config.projects) {
54
+ const linear = await this.linearProvider.forProject(candidate.id);
55
+ if (!linear)
56
+ continue;
57
+ try {
58
+ const liveIssue = await linear.getIssue(normalized.issue.id);
59
+ const hydrated = { ...normalized, issue: mergeIssueMetadata(normalized.issue, liveIssue) };
60
+ const resolved = resolveProject(this.config, hydrated.issue);
61
+ if (resolved)
62
+ return { project: resolved, normalized: hydrated };
63
+ }
64
+ catch {
65
+ // Continue scanning candidate projects until one can resolve the issue route.
66
+ }
67
+ }
68
+ return undefined;
69
+ }
70
+ }
@@ -0,0 +1,52 @@
1
+ export class DependencyReadinessHandler {
2
+ db;
3
+ peekPendingSessionWakeRunType;
4
+ constructor(db, peekPendingSessionWakeRunType) {
5
+ this.db = db;
6
+ this.peekPendingSessionWakeRunType = peekPendingSessionWakeRunType;
7
+ }
8
+ reconcile(projectId, blockerLinearIssueId) {
9
+ const newlyReady = [];
10
+ for (const dependent of this.db.issues.listDependents(projectId, blockerLinearIssueId)) {
11
+ const issue = this.db.issues.getIssue(projectId, dependent.linearIssueId);
12
+ if (!issue) {
13
+ continue;
14
+ }
15
+ const unresolved = this.db.issues.countUnresolvedBlockers(projectId, dependent.linearIssueId);
16
+ if (unresolved > 0) {
17
+ if (this.peekPendingSessionWakeRunType(projectId, dependent.linearIssueId) === "implementation"
18
+ && issue.activeRunId === undefined
19
+ && !this.db.issueSessions.hasPendingIssueSessionEvents(projectId, dependent.linearIssueId)) {
20
+ this.db.issues.upsertIssue({
21
+ projectId,
22
+ linearIssueId: dependent.linearIssueId,
23
+ pendingRunType: null,
24
+ pendingRunContextJson: null,
25
+ });
26
+ }
27
+ continue;
28
+ }
29
+ if (issue.factoryState !== "delegated"
30
+ || issue.activeRunId !== undefined
31
+ || this.db.issueSessions.hasPendingIssueSessionEvents(projectId, dependent.linearIssueId)) {
32
+ continue;
33
+ }
34
+ if (this.peekPendingSessionWakeRunType(projectId, dependent.linearIssueId) === "implementation") {
35
+ this.db.issues.upsertIssue({
36
+ projectId,
37
+ linearIssueId: dependent.linearIssueId,
38
+ pendingRunType: null,
39
+ pendingRunContextJson: null,
40
+ });
41
+ }
42
+ this.db.issueSessions.appendIssueSessionEventRespectingActiveLease(projectId, dependent.linearIssueId, {
43
+ projectId,
44
+ linearIssueId: dependent.linearIssueId,
45
+ eventType: "delegated",
46
+ dedupeKey: `delegated:${dependent.linearIssueId}`,
47
+ });
48
+ newlyReady.push(dependent.linearIssueId);
49
+ }
50
+ return newlyReady;
51
+ }
52
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patchrelay",
3
- "version": "0.36.11",
3
+ "version": "0.36.13",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "repository": {