@dahrk/linear 0.1.0 → 0.1.1
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 +24 -12
- package/dist/comments.d.ts +36 -0
- package/dist/comments.d.ts.map +1 -0
- package/dist/comments.js +104 -0
- package/dist/comments.js.map +1 -0
- package/dist/documents.d.ts +1 -15
- package/dist/documents.d.ts.map +1 -1
- package/dist/documents.js +37 -27
- package/dist/documents.js.map +1 -1
- package/dist/format-action.d.ts +25 -0
- package/dist/format-action.d.ts.map +1 -0
- package/dist/format-action.js +250 -0
- package/dist/format-action.js.map +1 -0
- package/dist/index.d.ts +113 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +182 -58
- package/dist/index.js.map +1 -1
- package/dist/issue-graph.d.ts +37 -0
- package/dist/issue-graph.d.ts.map +1 -0
- package/dist/issue-graph.js +125 -0
- package/dist/issue-graph.js.map +1 -0
- package/dist/issues.d.ts +3 -2
- package/dist/issues.d.ts.map +1 -1
- package/dist/issues.js +5 -10
- package/dist/issues.js.map +1 -1
- package/dist/labels.d.ts +47 -0
- package/dist/labels.d.ts.map +1 -1
- package/dist/labels.js +71 -23
- package/dist/labels.js.map +1 -1
- package/dist/linear-client.d.ts +51 -0
- package/dist/linear-client.d.ts.map +1 -1
- package/dist/linear-client.js +234 -34
- package/dist/linear-client.js.map +1 -1
- package/dist/oauth.d.ts +11 -10
- package/dist/oauth.d.ts.map +1 -1
- package/dist/oauth.js +35 -32
- package/dist/oauth.js.map +1 -1
- package/dist/recording-client.d.ts +20 -2
- package/dist/recording-client.d.ts.map +1 -1
- package/dist/recording-client.js +39 -1
- package/dist/recording-client.js.map +1 -1
- package/dist/responding-client.d.ts +49 -0
- package/dist/responding-client.d.ts.map +1 -0
- package/dist/responding-client.js +47 -0
- package/dist/responding-client.js.map +1 -0
- package/dist/teams.d.ts +20 -0
- package/dist/teams.d.ts.map +1 -0
- package/dist/teams.js +32 -0
- package/dist/teams.js.map +1 -0
- package/package.json +8 -10
- package/src/comments.ts +126 -0
- package/src/documents.ts +162 -0
- package/src/format-action.ts +279 -0
- package/src/index.ts +556 -0
- package/src/issue-graph.ts +169 -0
- package/src/issues.ts +93 -0
- package/src/labels.ts +254 -0
- package/src/linear-client.ts +449 -0
- package/src/oauth.ts +194 -0
- package/src/recording-client.ts +141 -0
- package/src/responding-client.ts +106 -0
- package/src/teams.ts +44 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetch the metadata of the issues one hop from a run's issue - parent, children, blockers, blocked,
|
|
3
|
+
* related - so the hub can snapshot a manifest into the run and tell the agent WHAT EXISTS around the
|
|
4
|
+
* ticket it is working.
|
|
5
|
+
*
|
|
6
|
+
* This is deliberately metadata only: identifier, title, relation, state. No descriptions, no comments,
|
|
7
|
+
* no documents. That keeps the manifest cheap enough to send on every run, and it is the piece that
|
|
8
|
+
* makes on-demand context work at all - an agent that cannot see there is a spike or an epic attached
|
|
9
|
+
* will never think to open one.
|
|
10
|
+
*
|
|
11
|
+
* Distinct from `fetchOpenBlockers` in `labels.ts`, which reads the same edges for the deterministic
|
|
12
|
+
* blocked guard: that one answers "may this run proceed" and feeds control flow, this one answers
|
|
13
|
+
* "what surrounds this ticket" and is context only. They are kept apart on purpose so a change to the
|
|
14
|
+
* manifest can never alter a guard.
|
|
15
|
+
*
|
|
16
|
+
* The `IssueGraphSource` seam keeps the assembly pure and unit-testable.
|
|
17
|
+
*/
|
|
18
|
+
import { LinearClient } from "@linear/sdk";
|
|
19
|
+
/** How many neighbours ride the manifest. Beyond this the prompt stops being a summary. */
|
|
20
|
+
export const MAX_RELATED_ISSUES = 50;
|
|
21
|
+
/** Stable ordering for the manifest: the structurally important edges first, so a truncated list keeps
|
|
22
|
+
* what matters. Parent and blockers change how the work should be done; `related` is a loose,
|
|
23
|
+
* human-curated edge and is the first thing worth losing. */
|
|
24
|
+
const RELATION_ORDER = {
|
|
25
|
+
parent: 0,
|
|
26
|
+
blocker: 1,
|
|
27
|
+
child: 2,
|
|
28
|
+
blocked: 3,
|
|
29
|
+
related: 4,
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Collect the issue's one-hop neighbourhood from a source: drop edges whose issue did not resolve or
|
|
33
|
+
* carries no identifier, de-dupe by identifier (an issue can be reachable by more than one edge -
|
|
34
|
+
* keep the structurally strongest, which is the lowest `RELATION_ORDER`), sort, and cap. Pure of any
|
|
35
|
+
* network.
|
|
36
|
+
*/
|
|
37
|
+
export async function collectRelatedIssues(source, issueId) {
|
|
38
|
+
const byKey = new Map();
|
|
39
|
+
for (const edge of await source.issueEdges(issueId)) {
|
|
40
|
+
const issue = edge.issue;
|
|
41
|
+
const key = issue?.identifier?.trim();
|
|
42
|
+
if (!issue || !key)
|
|
43
|
+
continue;
|
|
44
|
+
const candidate = {
|
|
45
|
+
key,
|
|
46
|
+
title: (issue.title ?? "").trim() || "Untitled issue",
|
|
47
|
+
relation: edge.relation,
|
|
48
|
+
stateName: (issue.stateName ?? "").trim() || "unknown",
|
|
49
|
+
stateType: (issue.stateType ?? "").trim() || "unknown",
|
|
50
|
+
url: issue.url ?? "",
|
|
51
|
+
};
|
|
52
|
+
const existing = byKey.get(key);
|
|
53
|
+
if (!existing || RELATION_ORDER[candidate.relation] < RELATION_ORDER[existing.relation]) {
|
|
54
|
+
byKey.set(key, candidate);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return [...byKey.values()]
|
|
58
|
+
.sort((a, b) => RELATION_ORDER[a.relation] - RELATION_ORDER[b.relation] || a.key.localeCompare(b.key))
|
|
59
|
+
.slice(0, MAX_RELATED_ISSUES);
|
|
60
|
+
}
|
|
61
|
+
/** The live `IssueGraphSource`, backed by a Linear bearer token. Uses the typed SDK. */
|
|
62
|
+
export function linearIssueGraphSource(token) {
|
|
63
|
+
const client = new LinearClient({ accessToken: token });
|
|
64
|
+
return {
|
|
65
|
+
async issueEdges(issueId) {
|
|
66
|
+
const issue = await client.issue(issueId);
|
|
67
|
+
// Resolve one neighbouring issue into the raw shape, including its state. Returns null when the
|
|
68
|
+
// issue or its state does not resolve, which the assembly then skips.
|
|
69
|
+
const shape = async (node) => {
|
|
70
|
+
if (!node)
|
|
71
|
+
return null;
|
|
72
|
+
const state = await node.state;
|
|
73
|
+
return {
|
|
74
|
+
...(node.identifier ? { identifier: node.identifier } : {}),
|
|
75
|
+
...(node.title ? { title: node.title } : {}),
|
|
76
|
+
...(node.url ? { url: node.url } : {}),
|
|
77
|
+
...(state?.name ? { stateName: state.name } : {}),
|
|
78
|
+
...(state?.type ? { stateType: state.type } : {}),
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
// The four reads run concurrently; each is independently capped. `relations` is what this issue
|
|
82
|
+
// blocks/relates to, `inverseRelations` is what points AT this issue - the direction matters, and
|
|
83
|
+
// getting it backwards is the bug called out on `fetchOpenBlockers` (labels.ts).
|
|
84
|
+
const [parent, children, relations, inverseRelations] = await Promise.all([
|
|
85
|
+
issue.parent,
|
|
86
|
+
issue.children({ first: 25 }),
|
|
87
|
+
issue.relations({ first: 25 }),
|
|
88
|
+
issue.inverseRelations({ first: 25 }),
|
|
89
|
+
]);
|
|
90
|
+
const edges = [];
|
|
91
|
+
const parentShape = await shape(parent);
|
|
92
|
+
if (parentShape)
|
|
93
|
+
edges.push({ relation: "parent", issue: parentShape });
|
|
94
|
+
for (const child of children.nodes) {
|
|
95
|
+
edges.push({ relation: "child", issue: await shape(child) });
|
|
96
|
+
}
|
|
97
|
+
// Outbound: `A blocks B` stored on A means B is blocked BY us; anything else is a plain relation.
|
|
98
|
+
for (const rel of relations.nodes) {
|
|
99
|
+
const related = await rel.relatedIssue;
|
|
100
|
+
edges.push({
|
|
101
|
+
relation: rel.type === "blocks" ? "blocked" : "related",
|
|
102
|
+
issue: await shape(related),
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
// Inbound: a `blocks` relation pointing at us means that issue is OUR blocker.
|
|
106
|
+
for (const rel of inverseRelations.nodes) {
|
|
107
|
+
const other = await rel.issue;
|
|
108
|
+
edges.push({
|
|
109
|
+
relation: rel.type === "blocks" ? "blocker" : "related",
|
|
110
|
+
issue: await shape(other),
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
return edges;
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Fetch the issue's one-hop neighbourhood as contract `RelatedIssue`s, ready to snapshot into a run.
|
|
119
|
+
* The single entry point the hub calls. A hard failure (auth, network) propagates so the caller can
|
|
120
|
+
* log and proceed with none.
|
|
121
|
+
*/
|
|
122
|
+
export async function fetchRelatedIssues(token, issueId) {
|
|
123
|
+
return collectRelatedIssues(linearIssueGraphSource(token), issueId);
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=issue-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue-graph.js","sourceRoot":"","sources":["../src/issue-graph.ts"],"names":[],"mappings":"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"}
|
package/dist/issues.d.ts
CHANGED
|
@@ -42,7 +42,8 @@ export declare function linearClientAuth(token: string): {
|
|
|
42
42
|
accessToken: string;
|
|
43
43
|
};
|
|
44
44
|
/** The live `TriageApi` backed by a Linear token (personal API key or OAuth access token). Resolves
|
|
45
|
-
* team
|
|
46
|
-
*
|
|
45
|
+
* team by key and optional project by name via server-side `filter` (verified on @linear/sdk 86.0.0,
|
|
46
|
+
* DHK-579: `TeamFilter.key`/`ProjectFilter.name` return exactly the expected node - the earlier
|
|
47
|
+
* paginate-then-match workaround is no longer needed). */
|
|
47
48
|
export declare function linearTriageApi(token: string): TriageApi;
|
|
48
49
|
//# sourceMappingURL=issues.d.ts.map
|
package/dist/issues.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issues.d.ts","sourceRoot":"","sources":["../src/issues.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,SAAS;IACxB;;uFAEmF;IACnF,WAAW,CAAC,KAAK,EAAE;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD;;uEAEmE;IACnE,kBAAkB,CAAC,KAAK,EAAE;QACxB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5B;;;sFAGkF;IAClF,YAAY,CAAC,KAAK,EAAE;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,EAAE,MAAM,CAAC;QACvB,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;KAC7B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnB;AAED;;;2FAG2F;AAC3F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAE5F;AAED
|
|
1
|
+
{"version":3,"file":"issues.d.ts","sourceRoot":"","sources":["../src/issues.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,SAAS;IACxB;;uFAEmF;IACnF,WAAW,CAAC,KAAK,EAAE;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD;;uEAEmE;IACnE,kBAAkB,CAAC,KAAK,EAAE;QACxB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5B;;;sFAGkF;IAClF,YAAY,CAAC,KAAK,EAAE;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,EAAE,MAAM,CAAC;QACvB,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;KAC7B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnB;AAED;;;2FAG2F;AAC3F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAE5F;AAED;;;2DAG2D;AAC3D,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CA0CxD"}
|
package/dist/issues.js
CHANGED
|
@@ -13,24 +13,19 @@ export function linearClientAuth(token) {
|
|
|
13
13
|
return token.startsWith("lin_api_") ? { apiKey: token } : { accessToken: token };
|
|
14
14
|
}
|
|
15
15
|
/** The live `TriageApi` backed by a Linear token (personal API key or OAuth access token). Resolves
|
|
16
|
-
* team
|
|
17
|
-
*
|
|
16
|
+
* team by key and optional project by name via server-side `filter` (verified on @linear/sdk 86.0.0,
|
|
17
|
+
* DHK-579: `TeamFilter.key`/`ProjectFilter.name` return exactly the expected node - the earlier
|
|
18
|
+
* paginate-then-match workaround is no longer needed). */
|
|
18
19
|
export function linearTriageApi(token) {
|
|
19
20
|
const client = new LinearClient(linearClientAuth(token));
|
|
20
21
|
return {
|
|
21
22
|
async createIssue(input) {
|
|
22
|
-
const
|
|
23
|
-
while (teams.pageInfo.hasNextPage)
|
|
24
|
-
await teams.fetchNext();
|
|
25
|
-
const team = teams.nodes.find((t) => t.key === input.teamKey);
|
|
23
|
+
const team = (await client.teams({ filter: { key: { eq: input.teamKey } } })).nodes[0];
|
|
26
24
|
if (!team)
|
|
27
25
|
throw new Error(`triage team not found: ${input.teamKey}`);
|
|
28
26
|
let projectId;
|
|
29
27
|
if (input.projectName) {
|
|
30
|
-
|
|
31
|
-
while (projects.pageInfo.hasNextPage)
|
|
32
|
-
await projects.fetchNext();
|
|
33
|
-
projectId = projects.nodes.find((p) => p.name === input.projectName)?.id;
|
|
28
|
+
projectId = (await client.projects({ filter: { name: { eq: input.projectName } } })).nodes[0]?.id;
|
|
34
29
|
}
|
|
35
30
|
const payload = await client.createIssue({
|
|
36
31
|
teamId: team.id,
|
package/dist/issues.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issues.js","sourceRoot":"","sources":["../src/issues.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAgC9D;;;2FAG2F;AAC3F,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,OAAO,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;AACnF,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"issues.js","sourceRoot":"","sources":["../src/issues.ts"],"names":[],"mappings":"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"}
|
package/dist/labels.d.ts
CHANGED
|
@@ -53,6 +53,53 @@ export declare function provisionRepoLabels(api: LabelApi, repoNames: Iterable<s
|
|
|
53
53
|
* feeds deterministic routing and is snapshotted into the run.
|
|
54
54
|
*/
|
|
55
55
|
export declare function fetchIssueProjectRepoLabels(token: string, issueId: string): Promise<string[]>;
|
|
56
|
+
/**
|
|
57
|
+
* Count an issue's child issues (DHK-412), so the hub's epic guard can decline a parent-of-children.
|
|
58
|
+
* The webhook payload carries an issue's `<parent-issue>` but never a listing of its children, so
|
|
59
|
+
* "has children" must be resolved with a read against the connection token. Returns 0 when the issue
|
|
60
|
+
* has none (or the field is empty). Capped at `first:1` - the guard only needs "any", not an exact
|
|
61
|
+
* total - so it stays a cheap intake read. Data assembly, not control flow: the count feeds the
|
|
62
|
+
* deterministic, no-LLM epic guard.
|
|
63
|
+
*/
|
|
64
|
+
export declare function fetchIssueChildCount(token: string, issueId: string): Promise<number>;
|
|
65
|
+
/** One issue that blocks another and has not settled yet. `identifier` is the human key (e.g.
|
|
66
|
+
* `DHK-777`) the decline note names; `stateName` is the team's own label for the state it sits in,
|
|
67
|
+
* carried for the note only - never matched on (see `fetchOpenBlockers`). */
|
|
68
|
+
export interface OpenBlocker {
|
|
69
|
+
identifier: string;
|
|
70
|
+
stateName: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Has a blocker finished, so it no longer blocks?
|
|
74
|
+
*
|
|
75
|
+
* Decided on the workflow state's `type` - Linear's own fixed vocabulary (`backlog`, `unstarted`,
|
|
76
|
+
* `started`, `completed`, `canceled`) - and NEVER on its name. Teams rename states freely: "Done"
|
|
77
|
+
* becomes "Shipped", "Released", "Merged". A name match would stop guarding for every one of those
|
|
78
|
+
* teams with nothing to notice, because the guard would simply never fire again.
|
|
79
|
+
*
|
|
80
|
+
* An absent/unknown type is treated as NOT settled: a blocker we cannot prove is finished is one we
|
|
81
|
+
* must assume is not. Pure, so the rule is pinned by a test rather than by a live Linear read.
|
|
82
|
+
*/
|
|
83
|
+
export declare function isBlockerSettled(stateType: string | undefined): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* The issues blocking `issueId` that are not finished yet, so the hub's blocked guard can decline a
|
|
86
|
+
* run that cannot possibly succeed. The webhook payload carries no relation data at all, so this must
|
|
87
|
+
* be resolved with a read against the connection token, exactly as `fetchIssueChildCount` resolves the
|
|
88
|
+
* epic signal. Returns an empty list when nothing blocks the issue, or when every blocker has settled.
|
|
89
|
+
*
|
|
90
|
+
* The direction matters: `A blocks B` is stored on A, so B reads it through `inverseRelations`. Reading
|
|
91
|
+
* `relations` instead would return what this issue blocks - the opposite question, and one that would
|
|
92
|
+
* silently never guard anything.
|
|
93
|
+
*
|
|
94
|
+
* "Settled" is decided on the state's `type` (`completed` / `canceled`), NEVER on its name. Teams rename
|
|
95
|
+
* workflow states freely - "Done" becomes "Shipped", "Released", "Merged" - and a name match would stop
|
|
96
|
+
* guarding for those teams without any error to notice. The type is Linear's own fixed vocabulary.
|
|
97
|
+
*
|
|
98
|
+
* Capped, like the child-count read: a ticket with more open blockers than the cap is still blocked, and
|
|
99
|
+
* the note naming the first few is enough to act on. Data assembly, not control flow: the list feeds the
|
|
100
|
+
* deterministic, no-LLM blocked guard.
|
|
101
|
+
*/
|
|
102
|
+
export declare function fetchOpenBlockers(token: string, issueId: string): Promise<OpenBlocker[]>;
|
|
56
103
|
/** The live `LabelApi` backed by a Linear bearer token (workspace-scoped labels). */
|
|
57
104
|
export declare function linearLabelApi(token: string): LabelApi;
|
|
58
105
|
/** The live `LabelApi` backed by a Linear bearer token, for **project** labels (a separate namespace
|
package/dist/labels.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,QAAQ;IACvB,qDAAqD;IACrD,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,yDAAyD;IACzD,WAAW,CAAC,KAAK,EAAE;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iGAAiG;IACjG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACrC;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,EACvB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,MAAM,EAAE,CAAC,CA0BnB;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,EACvB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,MAAM,EAAE,CAAC,CAMnB;AAED;;mGAEmG;AACnG,eAAO,MAAM,gBAAgB,SAAS,CAAC;AAEvC;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,QAAQ,EACb,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,EAC3B,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5B,OAAO,CAAC,MAAM,EAAE,CAAC,CAOnB;
|
|
1
|
+
{"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,QAAQ;IACvB,qDAAqD;IACrD,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,yDAAyD;IACzD,WAAW,CAAC,KAAK,EAAE;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iGAAiG;IACjG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACrC;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,EACvB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,MAAM,EAAE,CAAC,CA0BnB;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,EACvB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,MAAM,EAAE,CAAC,CAMnB;AAED;;mGAEmG;AACnG,eAAO,MAAM,gBAAgB,SAAS,CAAC;AAEvC;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,QAAQ,EACb,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,EAC3B,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5B,OAAO,CAAC,MAAM,EAAE,CAAC,CAOnB;AAED;;;;;;;GAOG;AACH,wBAAsB,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAOnG;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAK1F;AAED;;8EAE8E;AAC9E,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEvE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAc9F;AAED,qFAAqF;AACrF,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAsBtD;AAED;;mDAEmD;AACnD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAsBvD"}
|
package/dist/labels.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Trigger-label auto-provisioning (build spec section 14; plan item 7). A repository declares its
|
|
3
|
-
* workflows as `.
|
|
3
|
+
* workflows as `.dahrk/workflows/*.yaml`, each with a `select.label`; for those labels to be
|
|
4
4
|
* assignable in Linear they must exist in the workspace. Rather than make operators create them by
|
|
5
5
|
* hand, the onboarding path reads the workflow label set and creates any that are missing - once,
|
|
6
6
|
* idempotently - optionally grouped under a single "Dahrk workflow" label group.
|
|
@@ -70,7 +70,6 @@ export async function provisionRepoLabels(api, repoNames, opts = {}) {
|
|
|
70
70
|
describe: (name) => `Dahrk repository selector: ${name}`,
|
|
71
71
|
});
|
|
72
72
|
}
|
|
73
|
-
const GRAPHQL_URL = "https://api.linear.app/graphql";
|
|
74
73
|
/**
|
|
75
74
|
* Fetch the child names of the issue's **project** `repo` label group (project labels are a separate
|
|
76
75
|
* Linear namespace from issue labels, `Project.labels`). Returns the names of project labels whose
|
|
@@ -80,28 +79,77 @@ const GRAPHQL_URL = "https://api.linear.app/graphql";
|
|
|
80
79
|
* feeds deterministic routing and is snapshotted into the run.
|
|
81
80
|
*/
|
|
82
81
|
export async function fetchIssueProjectRepoLabels(token, issueId) {
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
82
|
+
const client = new LinearClient({ accessToken: token });
|
|
83
|
+
const issue = await client.issue(issueId);
|
|
84
|
+
const project = await issue.project;
|
|
85
|
+
if (!project)
|
|
86
|
+
return [];
|
|
87
|
+
const conn = await project.labels({ first: 100, filter: { parent: { name: { eqIgnoreCase: REPO_LABEL_GROUP } } } });
|
|
88
|
+
return conn.nodes.map((n) => n.name.trim());
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Count an issue's child issues (DHK-412), so the hub's epic guard can decline a parent-of-children.
|
|
92
|
+
* The webhook payload carries an issue's `<parent-issue>` but never a listing of its children, so
|
|
93
|
+
* "has children" must be resolved with a read against the connection token. Returns 0 when the issue
|
|
94
|
+
* has none (or the field is empty). Capped at `first:1` - the guard only needs "any", not an exact
|
|
95
|
+
* total - so it stays a cheap intake read. Data assembly, not control flow: the count feeds the
|
|
96
|
+
* deterministic, no-LLM epic guard.
|
|
97
|
+
*/
|
|
98
|
+
export async function fetchIssueChildCount(token, issueId) {
|
|
99
|
+
const client = new LinearClient({ accessToken: token });
|
|
100
|
+
const issue = await client.issue(issueId);
|
|
101
|
+
const conn = await issue.children({ first: 1 });
|
|
102
|
+
return conn.nodes.length;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Has a blocker finished, so it no longer blocks?
|
|
106
|
+
*
|
|
107
|
+
* Decided on the workflow state's `type` - Linear's own fixed vocabulary (`backlog`, `unstarted`,
|
|
108
|
+
* `started`, `completed`, `canceled`) - and NEVER on its name. Teams rename states freely: "Done"
|
|
109
|
+
* becomes "Shipped", "Released", "Merged". A name match would stop guarding for every one of those
|
|
110
|
+
* teams with nothing to notice, because the guard would simply never fire again.
|
|
111
|
+
*
|
|
112
|
+
* An absent/unknown type is treated as NOT settled: a blocker we cannot prove is finished is one we
|
|
113
|
+
* must assume is not. Pure, so the rule is pinned by a test rather than by a live Linear read.
|
|
114
|
+
*/
|
|
115
|
+
export function isBlockerSettled(stateType) {
|
|
116
|
+
return stateType === "completed" || stateType === "canceled";
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The issues blocking `issueId` that are not finished yet, so the hub's blocked guard can decline a
|
|
120
|
+
* run that cannot possibly succeed. The webhook payload carries no relation data at all, so this must
|
|
121
|
+
* be resolved with a read against the connection token, exactly as `fetchIssueChildCount` resolves the
|
|
122
|
+
* epic signal. Returns an empty list when nothing blocks the issue, or when every blocker has settled.
|
|
123
|
+
*
|
|
124
|
+
* The direction matters: `A blocks B` is stored on A, so B reads it through `inverseRelations`. Reading
|
|
125
|
+
* `relations` instead would return what this issue blocks - the opposite question, and one that would
|
|
126
|
+
* silently never guard anything.
|
|
127
|
+
*
|
|
128
|
+
* "Settled" is decided on the state's `type` (`completed` / `canceled`), NEVER on its name. Teams rename
|
|
129
|
+
* workflow states freely - "Done" becomes "Shipped", "Released", "Merged" - and a name match would stop
|
|
130
|
+
* guarding for those teams without any error to notice. The type is Linear's own fixed vocabulary.
|
|
131
|
+
*
|
|
132
|
+
* Capped, like the child-count read: a ticket with more open blockers than the cap is still blocked, and
|
|
133
|
+
* the note naming the first few is enough to act on. Data assembly, not control flow: the list feeds the
|
|
134
|
+
* deterministic, no-LLM blocked guard.
|
|
135
|
+
*/
|
|
136
|
+
export async function fetchOpenBlockers(token, issueId) {
|
|
137
|
+
const client = new LinearClient({ accessToken: token });
|
|
138
|
+
const issue = await client.issue(issueId);
|
|
139
|
+
const conn = await issue.inverseRelations({ first: 25 });
|
|
140
|
+
const open = [];
|
|
141
|
+
for (const relation of conn.nodes) {
|
|
142
|
+
if (relation.type !== "blocks")
|
|
143
|
+
continue;
|
|
144
|
+
const blocker = await relation.issue;
|
|
145
|
+
if (!blocker)
|
|
146
|
+
continue;
|
|
147
|
+
const state = await blocker.state;
|
|
148
|
+
if (isBlockerSettled(state?.type))
|
|
149
|
+
continue;
|
|
150
|
+
open.push({ identifier: blocker.identifier, stateName: state?.name ?? "unknown" });
|
|
103
151
|
}
|
|
104
|
-
return
|
|
152
|
+
return open;
|
|
105
153
|
}
|
|
106
154
|
/** The live `LabelApi` backed by a Linear bearer token (workspace-scoped labels). */
|
|
107
155
|
export function linearLabelApi(token) {
|
package/dist/labels.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"labels.js","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA0B3C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAa,EACb,KAAuB,EACvB,OAAyB,EAAE;IAE3B,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC;IAExC,IAAI,QAA4B,CAAC;IACjC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,QAAQ;YACN,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;gBAC5B,CAAC,MAAM,GAAG,CAAC,WAAW,CAAC;oBACrB,IAAI,EAAE,IAAI,CAAC,SAAS;oBACpB,OAAO,EAAE,IAAI;oBACb,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACzE,CAAC,CAAC,CAAC;IACR,CAAC;IAED,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAClC,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QACjC,MAAM,GAAG,CAAC,WAAW,CAAC;YACpB,IAAI;YACJ,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5C,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9D,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAClC,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,GAAa,EACb,KAAuB,EACvB,OAAyB,EAAE;IAE3B,OAAO,eAAe,CAAC,GAAG,EAAE,KAAK,EAAE;QACjC,GAAG,IAAI;QACP,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,+BAA+B,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChF,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,2BAA2B,IAAI,EAAE;KACtD,CAAC,CAAC;AACL,CAAC;AAED;;mGAEmG;AACnG,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEvC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,GAAa,EACb,SAA2B,EAC3B,OAA2B,EAAE;IAE7B,OAAO,eAAe,CAAC,GAAG,EAAE,SAAS,EAAE;QACrC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,SAAS,EAAE,gBAAgB;QAC3B,gBAAgB,EAAE,kCAAkC;QACpD,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,8BAA8B,IAAI,EAAE;KACzD,CAAC,CAAC;AACL,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"labels.js","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA0B3C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAa,EACb,KAAuB,EACvB,OAAyB,EAAE;IAE3B,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC;IAExC,IAAI,QAA4B,CAAC;IACjC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,QAAQ;YACN,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;gBAC5B,CAAC,MAAM,GAAG,CAAC,WAAW,CAAC;oBACrB,IAAI,EAAE,IAAI,CAAC,SAAS;oBACpB,OAAO,EAAE,IAAI;oBACb,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACzE,CAAC,CAAC,CAAC;IACR,CAAC;IAED,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAClC,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QACjC,MAAM,GAAG,CAAC,WAAW,CAAC;YACpB,IAAI;YACJ,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5C,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9D,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAClC,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,GAAa,EACb,KAAuB,EACvB,OAAyB,EAAE;IAE3B,OAAO,eAAe,CAAC,GAAG,EAAE,KAAK,EAAE;QACjC,GAAG,IAAI;QACP,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,+BAA+B,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChF,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,2BAA2B,IAAI,EAAE;KACtD,CAAC,CAAC;AACL,CAAC;AAED;;mGAEmG;AACnG,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEvC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,GAAa,EACb,SAA2B,EAC3B,OAA2B,EAAE;IAE7B,OAAO,eAAe,CAAC,GAAG,EAAE,SAAS,EAAE;QACrC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,SAAS,EAAE,gBAAgB;QAC3B,gBAAgB,EAAE,kCAAkC;QACpD,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,8BAA8B,IAAI,EAAE;KACzD,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,KAAa,EAAE,OAAe;IAC9E,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC;IACpC,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACxB,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,YAAY,EAAE,gBAAgB,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACpH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,KAAa,EAAE,OAAe;IACvE,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IAChD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;AAC3B,CAAC;AAUD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAA6B;IAC5D,OAAO,SAAS,KAAK,WAAW,IAAI,SAAS,KAAK,UAAU,CAAC;AAC/D,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAa,EAAE,OAAe;IACpE,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,gBAAgB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IACzD,MAAM,IAAI,GAAkB,EAAE,CAAC;IAC/B,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAClC,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ;YAAE,SAAS;QACzC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC;QACrC,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC;QAClC,IAAI,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC;YAAE,SAAS;QAC5C,IAAI,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,IAAI,SAAS,EAAE,CAAC,CAAC;IACrF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,OAAO;QACL,KAAK,CAAC,UAAU;YACd,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;YACxC,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW;gBAAE,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;YACzD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;YACtC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK;gBAAE,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;YAC9D,OAAO,GAAG,CAAC;QACb,CAAC;QACD,KAAK,CAAC,WAAW,CAAC,KAAK;YACrB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC;gBAC5C,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9C,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAChE,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACvD,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC5C,CAAC,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC;YACvC,OAAO,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC;QACzB,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;mDAEmD;AACnD,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,OAAO;QACL,KAAK,CAAC,UAAU;YACd,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW;gBAAE,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;YACzD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;YACtC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK;gBAAE,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;YAC9D,OAAO,GAAG,CAAC;QACb,CAAC;QACD,KAAK,CAAC,WAAW,CAAC,KAAK;YACrB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC;gBAC9C,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9C,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAChE,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACvD,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC5C,CAAC,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC;YACzC,OAAO,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC;QACzB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/linear-client.d.ts
CHANGED
|
@@ -1,3 +1,54 @@
|
|
|
1
1
|
import type { AgentSessionClient } from "./index.js";
|
|
2
|
+
/** The subset of a Linear workflow state that state-selection needs. Kept structural so the live
|
|
3
|
+
* SDK's `WorkflowState` nodes satisfy it and the pure selectors are unit-testable without the SDK. */
|
|
4
|
+
export interface StateLike {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
position: number;
|
|
8
|
+
type: string;
|
|
9
|
+
}
|
|
10
|
+
/** Find the review-target state the way `moveIssueToReview` does, so `startIssue` can EXCLUDE it.
|
|
11
|
+
* Linear has no "review" state type, so it is matched by name: an explicit configured name
|
|
12
|
+
* (`DAHRK_REVIEW_STATE_NAME`) when set, else the first review-ish name. */
|
|
13
|
+
export declare function findReviewState<T extends StateLike>(states: readonly T[], reviewName?: string): T | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Pick the team's working ("In Progress") state for a just-started run. A team can have MORE THAN
|
|
16
|
+
* ONE `started`-typed state (e.g. both "In Progress" and "In Review" are typed `started`), so the
|
|
17
|
+
* naive "lowest-position started state" is ambiguous and can wrongly land the ticket in In Review.
|
|
18
|
+
* Prefer an explicit working-name match (`/in progress|doing|started/i`), else the lowest-position
|
|
19
|
+
* `started` state that is NOT the review state. Returns `undefined` when there is no usable working
|
|
20
|
+
* state (so the caller reports a no-op rather than moving the ticket to review).
|
|
21
|
+
*/
|
|
22
|
+
export declare function selectStartState<T extends StateLike>(states: readonly T[], reviewName?: string): T | undefined;
|
|
23
|
+
/** Returns true when `delegateId` should be written on the issue.
|
|
24
|
+
* Skipping when already equal avoids the "assigned to you" notification on every re-run (DHK-263). */
|
|
25
|
+
export declare function shouldSetDelegate(issueDelegateId: string | undefined, viewerId: string): boolean;
|
|
26
|
+
/** A document as the issue-documents lookup sees it. Structural, so `findDocumentByTitle` is unit
|
|
27
|
+
* testable without standing up the SDK. */
|
|
28
|
+
export interface DocumentLike {
|
|
29
|
+
id: string;
|
|
30
|
+
/** Optional so the live SDK's non-null `title` is assignable and a null from the API cannot throw. */
|
|
31
|
+
title?: string;
|
|
32
|
+
url?: string;
|
|
33
|
+
}
|
|
34
|
+
/** The slice of a Linear issue the document lookup needs. */
|
|
35
|
+
export interface IssueDocuments {
|
|
36
|
+
documents(args: {
|
|
37
|
+
first: number;
|
|
38
|
+
}): Promise<{
|
|
39
|
+
nodes: DocumentLike[];
|
|
40
|
+
}>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The document already attached to this issue under `title`, or null when there is none. This is
|
|
44
|
+
* what gives `createDocument` its upsert: Linear keys documents by id only, so a title match on the
|
|
45
|
+
* issue is our stand-in.
|
|
46
|
+
*
|
|
47
|
+
* Titles are compared trimmed and case-insensitively, so a human who lightly re-cases the title does
|
|
48
|
+
* not cause the next run to fork a second copy. The read is bounded and unpaginated at 50, matching
|
|
49
|
+
* `linearDocumentSource.issueDocuments` in `documents.ts`: an issue carrying more than 50 documents
|
|
50
|
+
* silently drops the overflow, which is a deliberate limit rather than a bug.
|
|
51
|
+
*/
|
|
52
|
+
export declare function findDocumentByTitle(issue: IssueDocuments, title: string): Promise<DocumentLike | null>;
|
|
2
53
|
export declare function createLinearClient(token: string): AgentSessionClient;
|
|
3
54
|
//# sourceMappingURL=linear-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linear-client.d.ts","sourceRoot":"","sources":["../src/linear-client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"linear-client.d.ts","sourceRoot":"","sources":["../src/linear-client.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAEV,kBAAkB,EASnB,MAAM,YAAY,CAAC;AA6CpB;uGACuG;AACvG,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AASD;;4EAE4E;AAC5E,wBAAgB,eAAe,CAAC,CAAC,SAAS,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAK7G;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAO9G;AAED;uGACuG;AACvG,wBAAgB,iBAAiB,CAAC,eAAe,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEhG;AAED;4CAC4C;AAC5C,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,sGAAsG;IACtG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,6DAA6D;AAC7D,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,YAAY,EAAE,CAAA;KAAE,CAAC,CAAC;CACxE;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAK5G;AA6BD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,CA6QpE"}
|