@codyswann/lisa 2.295.0 → 2.295.2
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/cdk/create-only/.github/workflows/deploy.yml +0 -19
- package/dist/cli/gate-commands.d.ts +1 -3
- package/dist/cli/gate-commands.d.ts.map +1 -1
- package/dist/cli/gate-commands.js +0 -26
- package/dist/cli/gate-commands.js.map +1 -1
- package/dist/cli/index.d.ts +7 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +43 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/update-check.d.ts +0 -8
- package/dist/cli/update-check.d.ts.map +1 -1
- package/dist/cli/update-check.js +2 -4
- package/dist/cli/update-check.js.map +1 -1
- package/dist/core/project-config.d.ts +0 -3
- package/dist/core/project-config.d.ts.map +1 -1
- package/dist/core/project-config.js +40 -4
- package/dist/core/project-config.js.map +1 -1
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +10 -36
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/dist/sync/registry.d.ts.map +1 -1
- package/dist/sync/registry.js +6 -3
- package/dist/sync/registry.js.map +1 -1
- package/expo/create-only/.github/workflows/deploy.yml +0 -13
- package/expo/package-lisa/package.lisa.json +2 -0
- package/harper-fabric/create-only/.github/workflows/deploy.yml +0 -5
- package/nestjs/create-only/.github/workflows/deploy.yml +0 -14
- package/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/rules/eager/config-resolution.md +0 -9
- package/plugins/lisa/rules/reference/config-resolution.md +0 -59
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/rules/eager/config-resolution.md +0 -9
- package/plugins/lisa-copilot/rules/reference/config-resolution.md +0 -59
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +0 -59
- package/plugins/lisa-cursor/rules/config-resolution.mdc +0 -9
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/rules/eager/config-resolution.md +0 -9
- package/plugins/src/base/rules/reference/config-resolution.md +0 -59
- package/rails/create-only/.github/workflows/deploy.yml +0 -5
- package/typescript/copy-overwrite/.github/GITHUB_ACTIONS.md +0 -28
- package/typescript/package-lisa/package.lisa.json +2 -0
- package/dist/cli/deploy-status-adapter-github.d.ts +0 -20
- package/dist/cli/deploy-status-adapter-github.d.ts.map +0 -1
- package/dist/cli/deploy-status-adapter-github.js +0 -167
- package/dist/cli/deploy-status-adapter-github.js.map +0 -1
- package/dist/cli/deploy-status-adapter-jira.d.ts +0 -18
- package/dist/cli/deploy-status-adapter-jira.d.ts.map +0 -1
- package/dist/cli/deploy-status-adapter-jira.js +0 -215
- package/dist/cli/deploy-status-adapter-jira.js.map +0 -1
- package/dist/cli/deploy-status-adapter-linear.d.ts +0 -16
- package/dist/cli/deploy-status-adapter-linear.d.ts.map +0 -1
- package/dist/cli/deploy-status-adapter-linear.js +0 -204
- package/dist/cli/deploy-status-adapter-linear.js.map +0 -1
- package/dist/cli/deploy-status-adapter-shared.d.ts +0 -57
- package/dist/cli/deploy-status-adapter-shared.d.ts.map +0 -1
- package/dist/cli/deploy-status-adapter-shared.js +0 -62
- package/dist/cli/deploy-status-adapter-shared.js.map +0 -1
- package/dist/cli/deploy-status-adapter.d.ts +0 -49
- package/dist/cli/deploy-status-adapter.d.ts.map +0 -1
- package/dist/cli/deploy-status-adapter.js +0 -87
- package/dist/cli/deploy-status-adapter.js.map +0 -1
- package/dist/cli/deploy-status-refs.d.ts +0 -70
- package/dist/cli/deploy-status-refs.d.ts.map +0 -1
- package/dist/cli/deploy-status-refs.js +0 -195
- package/dist/cli/deploy-status-refs.js.map +0 -1
- package/dist/cli/deploy-status-sync-cmd.d.ts +0 -23
- package/dist/cli/deploy-status-sync-cmd.d.ts.map +0 -1
- package/dist/cli/deploy-status-sync-cmd.js +0 -75
- package/dist/cli/deploy-status-sync-cmd.js.map +0 -1
- package/dist/cli/deploy-status-sync-engine.d.ts +0 -49
- package/dist/cli/deploy-status-sync-engine.d.ts.map +0 -1
- package/dist/cli/deploy-status-sync-engine.js +0 -214
- package/dist/cli/deploy-status-sync-engine.js.map +0 -1
- package/dist/cli/deploy-status-sync-exec.d.ts +0 -73
- package/dist/cli/deploy-status-sync-exec.d.ts.map +0 -1
- package/dist/cli/deploy-status-sync-exec.js +0 -95
- package/dist/cli/deploy-status-sync-exec.js.map +0 -1
- package/dist/cli/kane-commands.d.ts +0 -21
- package/dist/cli/kane-commands.d.ts.map +0 -1
- package/dist/cli/kane-commands.js +0 -44
- package/dist/cli/kane-commands.js.map +0 -1
- package/dist/core/config-field-validation.d.ts +0 -19
- package/dist/core/config-field-validation.d.ts.map +0 -1
- package/dist/core/config-field-validation.js +0 -69
- package/dist/core/config-field-validation.js.map +0 -1
- package/dist/core/deploy-status-sync.d.ts +0 -103
- package/dist/core/deploy-status-sync.d.ts.map +0 -1
- package/dist/core/deploy-status-sync.js +0 -339
- package/dist/core/deploy-status-sync.js.map +0 -1
- package/dist/core/deploy-status-transition.d.ts +0 -97
- package/dist/core/deploy-status-transition.d.ts.map +0 -1
- package/dist/core/deploy-status-transition.js +0 -134
- package/dist/core/deploy-status-transition.js.map +0 -1
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Jira tracker adapter for deploy-status-sync over the Jira Cloud REST API.
|
|
3
|
-
*
|
|
4
|
-
* Contract-tested only in DSS-2 (unit tests inject a recording fetch); DSS-7
|
|
5
|
-
* flips it live through the same factory. Writes go through the cloudId
|
|
6
|
-
* gateway (`api.atlassian.com/ex/jira/<cloudId>`); transitions resolve the
|
|
7
|
-
* transition id first, then POST it. Credentials travel only in the Basic
|
|
8
|
-
* `Authorization` header — never in argv. Native closure is a no-op: in Jira
|
|
9
|
-
* the terminal done-category status IS closure.
|
|
10
|
-
* @module cli/deploy-status-adapter-jira
|
|
11
|
-
*/
|
|
12
|
-
import { DEPLOY_STATUS_SYNC_MARKER, } from "../core/deploy-status-transition.js";
|
|
13
|
-
import { getProcessEnv } from "./update-check.js";
|
|
14
|
-
/**
|
|
15
|
-
* Build the ADF document for a managed comment body: one paragraph node per
|
|
16
|
-
* line — ADF text nodes must not carry raw newline characters (Jira rejects
|
|
17
|
-
* or mangles them), so the body is split on `\n` and a blank line becomes an
|
|
18
|
-
* empty paragraph.
|
|
19
|
-
* @param text - Plain comment text (may span multiple lines)
|
|
20
|
-
* @returns ADF document
|
|
21
|
-
*/
|
|
22
|
-
function adfDocument(text) {
|
|
23
|
-
return {
|
|
24
|
-
type: "doc",
|
|
25
|
-
version: 1,
|
|
26
|
-
content: text.split("\n").map(line => ({
|
|
27
|
-
type: "paragraph",
|
|
28
|
-
content: line.length === 0 ? [] : [{ type: "text", text: line }],
|
|
29
|
-
})),
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Extract the first text node from an ADF comment body.
|
|
34
|
-
* @param body - ADF body value
|
|
35
|
-
* @returns The first text run, or empty string
|
|
36
|
-
*/
|
|
37
|
-
function adfFirstText(body) {
|
|
38
|
-
const doc = body;
|
|
39
|
-
const text = doc.content?.[0]?.content?.[0]?.text;
|
|
40
|
-
return typeof text === "string" ? text : "";
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Project an ADF comment body onto plain text: text nodes joined per
|
|
44
|
-
* paragraph, paragraphs joined with newlines. This is the unchanged-check
|
|
45
|
-
* comparison basis — Jira round-trips ADF with its own key order and extra
|
|
46
|
-
* fields (attrs, marks), so a raw JSON comparison would report a semantic
|
|
47
|
-
* no-change as different and issue a redundant PUT on every run.
|
|
48
|
-
* @param body - ADF body value
|
|
49
|
-
* @returns Plain-text projection of the document
|
|
50
|
-
*/
|
|
51
|
-
function adfPlainText(body) {
|
|
52
|
-
const doc = body;
|
|
53
|
-
return (doc.content ?? [])
|
|
54
|
-
.map(paragraph => (paragraph.content ?? [])
|
|
55
|
-
.map(node => (typeof node.text === "string" ? node.text : ""))
|
|
56
|
-
.join(""))
|
|
57
|
-
.join("\n");
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Whether a Jira status payload sits in the done category.
|
|
61
|
-
* @param status - Jira status field value
|
|
62
|
-
* @returns True for done-category statuses
|
|
63
|
-
*/
|
|
64
|
-
function isDoneCategory(status) {
|
|
65
|
-
const key = status.statusCategory
|
|
66
|
-
?.key;
|
|
67
|
-
return key === "done";
|
|
68
|
-
}
|
|
69
|
-
/** The only host shape the site fallback may target. */
|
|
70
|
-
const SITE_HOST_PATTERN = /^[a-z0-9-]+\.atlassian\.net$/i;
|
|
71
|
-
/**
|
|
72
|
-
* Resolve the REST base URL: the cloudId gateway when configured, else the
|
|
73
|
-
* `atlassian.site` fallback — which must be a bare `*.atlassian.net` host.
|
|
74
|
-
* Anything else (paths, foreign hosts) is rejected decision-readably before
|
|
75
|
-
* any request is made, so a poisoned config value cannot steer credentialed
|
|
76
|
-
* requests to an attacker-chosen server.
|
|
77
|
-
* @param options - Cloud id / site fallback
|
|
78
|
-
* @returns Base URL, or undefined when neither source is configured
|
|
79
|
-
*/
|
|
80
|
-
function resolveBaseUrl(options) {
|
|
81
|
-
if (options.cloudId !== undefined) {
|
|
82
|
-
return `https://api.atlassian.com/ex/jira/${encodeURIComponent(options.cloudId)}`;
|
|
83
|
-
}
|
|
84
|
-
const site = (options.site ?? "")
|
|
85
|
-
.replace(/^https?:\/\//, "")
|
|
86
|
-
.replace(/\/$/, "");
|
|
87
|
-
if (site.length === 0)
|
|
88
|
-
return undefined;
|
|
89
|
-
if (!SITE_HOST_PATTERN.test(site)) {
|
|
90
|
-
throw new Error(`Invalid atlassian.site "${options.site ?? ""}" in .lisa.config.json: expected a bare "<site>.atlassian.net" host. Set atlassian.cloudId (preferred) or fix atlassian.site.`);
|
|
91
|
-
}
|
|
92
|
-
return `https://${site}`;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Build the authenticated REST transport (Basic auth header only — the
|
|
96
|
-
* token never reaches argv or the URL).
|
|
97
|
-
* @param options - Cloud id / site / login fallback
|
|
98
|
-
* @param deps - Injectable fetch and env
|
|
99
|
-
* @returns Bound transport
|
|
100
|
-
*/
|
|
101
|
-
function createRequest(options, deps) {
|
|
102
|
-
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
103
|
-
return async (path, init = {}) => {
|
|
104
|
-
const env = deps.env ?? getProcessEnv();
|
|
105
|
-
const token = env.JIRA_API_TOKEN ?? env.ATLASSIAN_API_TOKEN;
|
|
106
|
-
const login = env.JIRA_LOGIN ?? options.email;
|
|
107
|
-
const baseUrl = resolveBaseUrl(options);
|
|
108
|
-
if (token === undefined || login === undefined || baseUrl === undefined) {
|
|
109
|
-
throw new Error("Jira credentials not found: set JIRA_API_TOKEN or ATLASSIAN_API_TOKEN (plus JIRA_LOGIN or atlassian.email) and configure atlassian.cloudId");
|
|
110
|
-
}
|
|
111
|
-
const basic = Buffer.from(`${login}:${token}`).toString("base64");
|
|
112
|
-
const response = await fetchImpl(`${baseUrl}${path}`, {
|
|
113
|
-
method: init.method ?? "GET",
|
|
114
|
-
headers: {
|
|
115
|
-
Authorization: `Basic ${basic}`,
|
|
116
|
-
Accept: "application/json",
|
|
117
|
-
...(init.body === undefined
|
|
118
|
-
? {}
|
|
119
|
-
: { "Content-Type": "application/json" }),
|
|
120
|
-
},
|
|
121
|
-
...(init.body === undefined ? {} : { body: init.body }),
|
|
122
|
-
});
|
|
123
|
-
if (!response.ok) {
|
|
124
|
-
throw new Error(`Jira request ${init.method ?? "GET"} ${path} failed with HTTP ${String(response.status)}`);
|
|
125
|
-
}
|
|
126
|
-
const text = await response.text();
|
|
127
|
-
return text.length > 0 ? JSON.parse(text) : {};
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Fetch the vendor-neutral state snapshot for one issue.
|
|
132
|
-
* @param request - Bound transport
|
|
133
|
-
* @param ref - Issue key
|
|
134
|
-
* @returns Item state
|
|
135
|
-
*/
|
|
136
|
-
async function fetchState(request, ref) {
|
|
137
|
-
const issue = (await request(`/rest/api/3/issue/${ref}?fields=status,issuetype,subtasks`));
|
|
138
|
-
const status = issue.fields?.status;
|
|
139
|
-
const type = issue.fields?.issuetype?.name;
|
|
140
|
-
const openChildren = (issue.fields?.subtasks ?? []).filter(subtask => !isDoneCategory(subtask.fields?.status)).length;
|
|
141
|
-
return {
|
|
142
|
-
ref,
|
|
143
|
-
...(type === undefined ? {} : { type }),
|
|
144
|
-
openChildren,
|
|
145
|
-
...(status?.name === undefined ? {} : { currentStatus: status.name }),
|
|
146
|
-
closed: isDoneCategory(status),
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Resolve the transition id reaching the done status, then POST it.
|
|
151
|
-
* @param request - Bound transport
|
|
152
|
-
* @param ref - Issue key
|
|
153
|
-
* @param doneStatus - Target status name (config-sourced)
|
|
154
|
-
*/
|
|
155
|
-
async function transition(request, ref, doneStatus) {
|
|
156
|
-
const payload = (await request(`/rest/api/3/issue/${ref}/transitions`));
|
|
157
|
-
const match = (payload.transitions ?? []).find(candidate => (candidate.to?.name ?? "").toLowerCase() === doneStatus.toLowerCase());
|
|
158
|
-
if (match?.id === undefined) {
|
|
159
|
-
throw new Error(`Jira issue ${ref} has no transition reaching "${doneStatus}" — fix the workflow or jira.workflow.done`);
|
|
160
|
-
}
|
|
161
|
-
await request(`/rest/api/3/issue/${ref}/transitions`, {
|
|
162
|
-
method: "POST",
|
|
163
|
-
body: JSON.stringify({ transition: { id: match.id } }),
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Find-or-update the single marker-managed ADF comment on the issue.
|
|
168
|
-
* @param request - Bound transport
|
|
169
|
-
* @param ref - Issue key
|
|
170
|
-
* @param body - Deterministic plain-text comment body
|
|
171
|
-
* @returns Upsert outcome
|
|
172
|
-
*/
|
|
173
|
-
async function upsertComment(request, ref, body) {
|
|
174
|
-
// Bounded page, newest first: the marker comment is recent by
|
|
175
|
-
// construction. Live multi-page walking is DSS-7 acceptance scope.
|
|
176
|
-
const payload = (await request(`/rest/api/3/issue/${ref}/comment?maxResults=100&orderBy=-created`));
|
|
177
|
-
const existing = (payload.comments ?? []).find(comment => adfFirstText(comment.body).startsWith(DEPLOY_STATUS_SYNC_MARKER));
|
|
178
|
-
const doc = adfDocument(body);
|
|
179
|
-
if (existing === undefined) {
|
|
180
|
-
await request(`/rest/api/3/issue/${ref}/comment`, {
|
|
181
|
-
method: "POST",
|
|
182
|
-
body: JSON.stringify({ body: doc }),
|
|
183
|
-
});
|
|
184
|
-
return "created";
|
|
185
|
-
}
|
|
186
|
-
// Compare on the plain-text projection, not raw JSON — the server-stored
|
|
187
|
-
// ADF is normalized (key order, attrs/marks defaults) and would never
|
|
188
|
-
// byte-match the freshly built document.
|
|
189
|
-
if (adfPlainText(existing.body) === body) {
|
|
190
|
-
return "unchanged";
|
|
191
|
-
}
|
|
192
|
-
await request(`/rest/api/3/issue/${ref}/comment/${existing.id ?? ""}`, {
|
|
193
|
-
method: "PUT",
|
|
194
|
-
body: JSON.stringify({ body: doc }),
|
|
195
|
-
});
|
|
196
|
-
return "updated";
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Create the Jira adapter.
|
|
200
|
-
* @param options - Cloud id / site / login fallback
|
|
201
|
-
* @param deps - Injectable fetch and env
|
|
202
|
-
* @returns Tracker adapter over the Jira REST API
|
|
203
|
-
*/
|
|
204
|
-
export function createJiraAdapter(options, deps = {}) {
|
|
205
|
-
const request = createRequest(options, deps);
|
|
206
|
-
return {
|
|
207
|
-
fetchItemState: ref => fetchState(request, ref),
|
|
208
|
-
transitionToDone: (ref, doneStatus) => transition(request, ref, doneStatus),
|
|
209
|
-
upsertManagedComment: (ref, body) => upsertComment(request, ref, body),
|
|
210
|
-
// Jira has no separate close: the terminal done-category status IS the
|
|
211
|
-
// native closure, so this is deliberately a zero-request no-op.
|
|
212
|
-
closeNatively: () => Promise.resolve(),
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
//# sourceMappingURL=deploy-status-adapter-jira.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deploy-status-adapter-jira.js","sourceRoot":"","sources":["../../src/cli/deploy-status-adapter-jira.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EACL,yBAAyB,GAE1B,MAAM,qCAAqC,CAAC;AAM7C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AA+BlD;;;;;;;GAOG;AACH,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO;QACL,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,CAAC;QACV,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACrC,IAAI,EAAE,WAAoB;YAC1B,OAAO,EAAE,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;SAC1E,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,YAAY,CAAC,IAAa;IACjC,MAAM,GAAG,GAAG,IAEX,CAAC;IACF,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;IAClD,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;AAC9C,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,YAAY,CAAC,IAAa;IACjC,MAAM,GAAG,GAAG,IAEX,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;SACvB,GAAG,CAAC,SAAS,CAAC,EAAE,CACf,CAAC,SAAS,CAAC,OAAO,IAAI,EAAE,CAAC;SACtB,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SAC7D,IAAI,CAAC,EAAE,CAAC,CACZ;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CAAC,MAAe;IACrC,MAAM,GAAG,GAAI,MAAiD,CAAC,cAAc;QAC3E,EAAE,GAAG,CAAC;IACR,OAAO,GAAG,KAAK,MAAM,CAAC;AACxB,CAAC;AAED,wDAAwD;AACxD,MAAM,iBAAiB,GAAG,+BAA+B,CAAC;AAE1D;;;;;;;;GAQG;AACH,SAAS,cAAc,CAAC,OAA2B;IACjD,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAClC,OAAO,qCAAqC,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;IACpF,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;SAC9B,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC;SAC3B,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACtB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACxC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CACb,2BAA2B,OAAO,CAAC,IAAI,IAAI,EAAE,+HAA+H,CAC7K,CAAC;IACJ,CAAC;IACD,OAAO,WAAW,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED;;;;;;GAMG;AACH,SAAS,aAAa,CACpB,OAA2B,EAC3B,IAAwB;IAExB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC;IAC1C,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,EAAE,EAAE;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,aAAa,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,GAAG,CAAC,cAAc,IAAI,GAAG,CAAC,mBAAmB,CAAC;QAC5D,MAAM,KAAK,GAAG,GAAG,CAAC,UAAU,IAAI,OAAO,CAAC,KAAK,CAAC;QAC9C,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YACxE,MAAM,IAAI,KAAK,CACb,4IAA4I,CAC7I,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,IAAI,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAClE,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,OAAO,GAAG,IAAI,EAAE,EAAE;YACpD,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK;YAC5B,OAAO,EAAE;gBACP,aAAa,EAAE,SAAS,KAAK,EAAE;gBAC/B,MAAM,EAAE,kBAAkB;gBAC1B,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS;oBACzB,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC;aAC5C;YACD,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;SACxD,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,gBAAgB,IAAI,CAAC,MAAM,IAAI,KAAK,IAAI,IAAI,qBAAqB,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAC3F,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAa,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9D,CAAC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,UAAU,CACvB,OAAoB,EACpB,GAAW;IAEX,MAAM,KAAK,GAAG,CAAC,MAAM,OAAO,CAC1B,qBAAqB,GAAG,mCAAmC,CAC5D,CAMA,CAAC;IACF,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC;IACpC,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC;IAC3C,MAAM,YAAY,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC,MAAM,CACxD,OAAO,CAAC,EAAE,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CACnD,CAAC,MAAM,CAAC;IACT,OAAO;QACL,GAAG;QACH,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;QACvC,YAAY;QACZ,GAAG,CAAC,MAAM,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;QACrE,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC;KAC/B,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,UAAU,CACvB,OAAoB,EACpB,GAAW,EACX,UAAkB;IAElB,MAAM,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,qBAAqB,GAAG,cAAc,CAAC,CAErE,CAAC;IACF,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,CAC5C,SAAS,CAAC,EAAE,CACV,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,UAAU,CAAC,WAAW,EAAE,CACxE,CAAC;IACF,IAAI,KAAK,EAAE,EAAE,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CACb,cAAc,GAAG,gCAAgC,UAAU,4CAA4C,CACxG,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,CAAC,qBAAqB,GAAG,cAAc,EAAE;QACpD,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;KACvD,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,aAAa,CAC1B,OAAoB,EACpB,GAAW,EACX,IAAY;IAEZ,8DAA8D;IAC9D,mEAAmE;IACnE,MAAM,OAAO,GAAG,CAAC,MAAM,OAAO,CAC5B,qBAAqB,GAAG,0CAA0C,CACnE,CAEA,CAAC;IACF,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CACvD,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,yBAAyB,CAAC,CACjE,CAAC;IACF,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,OAAO,CAAC,qBAAqB,GAAG,UAAU,EAAE;YAChD,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;SACpC,CAAC,CAAC;QACH,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,yEAAyE;IACzE,sEAAsE;IACtE,yCAAyC;IACzC,IAAI,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QACzC,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,MAAM,OAAO,CAAC,qBAAqB,GAAG,YAAY,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;QACrE,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;KACpC,CAAC,CAAC;IACH,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAA2B,EAC3B,OAA2B,EAAE;IAE7B,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC7C,OAAO;QACL,cAAc,EAAE,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC;QAC/C,gBAAgB,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,EAAE,UAAU,CAAC;QAC3E,oBAAoB,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC;QACtE,uEAAuE;QACvE,gEAAgE;QAChE,aAAa,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE;KACvC,CAAC;AACJ,CAAC"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { type TrackerAdapter, type TrackerAdapterDeps } from "./deploy-status-adapter-shared.js";
|
|
2
|
-
/** Construction options for {@link createLinearAdapter}. */
|
|
3
|
-
export interface LinearAdapterOptions {
|
|
4
|
-
/** Linear workspace slug (credential scoping + keychain account) */
|
|
5
|
-
readonly workspace: string;
|
|
6
|
-
/** Ladder done vocabulary, lowest rung first (config-sourced) */
|
|
7
|
-
readonly doneStatuses: readonly string[];
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Create the Linear adapter.
|
|
11
|
-
* @param options - Workspace and done vocabulary
|
|
12
|
-
* @param deps - Injectable fetch, env, and secret reader
|
|
13
|
-
* @returns Tracker adapter over the Linear GraphQL API
|
|
14
|
-
*/
|
|
15
|
-
export declare function createLinearAdapter(options: LinearAdapterOptions, deps?: TrackerAdapterDeps): TrackerAdapter;
|
|
16
|
-
//# sourceMappingURL=deploy-status-adapter-linear.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deploy-status-adapter-linear.d.ts","sourceRoot":"","sources":["../../src/cli/deploy-status-adapter-linear.ts"],"names":[],"mappings":"AAcA,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACxB,MAAM,mCAAmC,CAAC;AAG3C,4DAA4D;AAC5D,MAAM,WAAW,oBAAoB;IACnC,oEAAoE;IACpE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iEAAiE;IACjE,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C;AAqQD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,GAAE,kBAAuB,GAC5B,cAAc,CAWhB"}
|
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Linear tracker adapter for deploy-status-sync over the Linear GraphQL API.
|
|
3
|
-
*
|
|
4
|
-
* Contract-tested only in DSS-2 (unit tests inject a recording fetch); DSS-6
|
|
5
|
-
* flips it live by supplying real deps through the same factory. The API key
|
|
6
|
-
* travels only in the raw `Authorization` header (Linear expects no Bearer
|
|
7
|
-
* prefix) — never in argv.
|
|
8
|
-
* @module cli/deploy-status-adapter-linear
|
|
9
|
-
*/
|
|
10
|
-
import { runKaneCommand } from "../core/kane-cli-process.js";
|
|
11
|
-
import { DEPLOY_STATUS_SYNC_MARKER, } from "../core/deploy-status-transition.js";
|
|
12
|
-
import { deriveLabelState, } from "./deploy-status-adapter-shared.js";
|
|
13
|
-
import { getProcessEnv } from "./update-check.js";
|
|
14
|
-
const GRAPHQL_URL = "https://api.linear.app/graphql";
|
|
15
|
-
const TERMINAL_STATE_TYPES = new Set(["completed", "canceled", "cancelled"]);
|
|
16
|
-
// children is bounded explicitly — Linear's default connection page size
|
|
17
|
-
// (50) would silently under-count openChildren on large containers.
|
|
18
|
-
const ISSUE_STATE_QUERY = "query($id:String!){issue(id:$id){id identifier state{name type} labels{nodes{name}} children(first:100){nodes{state{type}}}}}";
|
|
19
|
-
const ISSUE_ID_QUERY = "query($id:String!){issue(id:$id){id}}";
|
|
20
|
-
const LABEL_ID_QUERY = "query($name:String!){issueLabels(filter:{name:{eq:$name}}){nodes{id name}}}";
|
|
21
|
-
const ADD_LABEL_MUTATION = "mutation($issueId:String!,$labelId:String!){issueAddLabel(id:$issueId,labelId:$labelId){success}}";
|
|
22
|
-
// Bounded first page — live pagination is DSS-6 acceptance scope.
|
|
23
|
-
const COMMENTS_QUERY = "query($id:String!){issue(id:$id){id comments(first:100){nodes{id body}}}}";
|
|
24
|
-
const COMMENT_CREATE_MUTATION = "mutation($issueId:String!,$body:String!){commentCreate(input:{issueId:$issueId,body:$body}){success}}";
|
|
25
|
-
const COMMENT_UPDATE_MUTATION = "mutation($commentId:String!,$body:String!){commentUpdate(id:$commentId,input:{body:$body}){success}}";
|
|
26
|
-
const TEAM_STATES_QUERY = "query($id:String!){issue(id:$id){id team{states{nodes{id name type}}}}}";
|
|
27
|
-
const ISSUE_UPDATE_STATE_MUTATION = "mutation($issueId:String!,$stateId:String!){issueUpdate(id:$issueId,input:{stateId:$stateId}){success}}";
|
|
28
|
-
/**
|
|
29
|
-
* Read the darwin keychain entry for a Linear workspace.
|
|
30
|
-
* @param service - Keychain service name
|
|
31
|
-
* @param account - Keychain account (workspace)
|
|
32
|
-
* @returns Stored secret, or undefined when absent
|
|
33
|
-
*/
|
|
34
|
-
async function readKeychainSecret(service, account) {
|
|
35
|
-
if (process.platform !== "darwin")
|
|
36
|
-
return undefined;
|
|
37
|
-
const result = await runKaneCommand("security", ["find-generic-password", "-s", service, "-a", account, "-w"], { cwd: ".", timeoutMs: 15_000, env: getProcessEnv() });
|
|
38
|
-
const secret = result.stdout.trim();
|
|
39
|
-
return result.exitCode === 0 && secret.length > 0 ? secret : undefined;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Resolve the Linear API key: `LINEAR_API_KEY`, the workspace-suffixed
|
|
43
|
-
* variable, then the darwin `lisa-linear` keychain entry.
|
|
44
|
-
* @param workspace - Workspace slug
|
|
45
|
-
* @param deps - Injectable env and secret reader
|
|
46
|
-
* @returns The API key
|
|
47
|
-
*/
|
|
48
|
-
async function resolveLinearKey(workspace, deps) {
|
|
49
|
-
const env = deps.env ?? getProcessEnv();
|
|
50
|
-
const direct = env.LINEAR_API_KEY;
|
|
51
|
-
if (direct !== undefined && direct.length > 0)
|
|
52
|
-
return direct;
|
|
53
|
-
const suffix = workspace.toLowerCase().replace(/-/g, "_");
|
|
54
|
-
const scoped = env[`LINEAR_API_KEY_${suffix}`];
|
|
55
|
-
if (scoped !== undefined && scoped.length > 0)
|
|
56
|
-
return scoped;
|
|
57
|
-
const readSecret = deps.readSecret ?? readKeychainSecret;
|
|
58
|
-
const keychain = await readSecret("lisa-linear", workspace);
|
|
59
|
-
if (keychain !== undefined && keychain.length > 0)
|
|
60
|
-
return keychain;
|
|
61
|
-
throw new Error(`Linear credentials not found: set LINEAR_API_KEY (or LINEAR_API_KEY_${suffix}, or a darwin "lisa-linear" keychain entry for ${workspace})`);
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Build the GraphQL transport (key resolved per request, header-only).
|
|
65
|
-
* @param workspace - Workspace slug for credential resolution
|
|
66
|
-
* @param deps - Injectable fetch, env, and secret reader
|
|
67
|
-
* @returns Bound GraphQL transport
|
|
68
|
-
*/
|
|
69
|
-
function createGraphql(workspace, deps) {
|
|
70
|
-
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
71
|
-
return async (query, variables) => {
|
|
72
|
-
const key = await resolveLinearKey(workspace, deps);
|
|
73
|
-
const response = await fetchImpl(GRAPHQL_URL, {
|
|
74
|
-
method: "POST",
|
|
75
|
-
headers: { Authorization: key, "Content-Type": "application/json" },
|
|
76
|
-
body: JSON.stringify({ query, variables }),
|
|
77
|
-
});
|
|
78
|
-
// Status-only error: a non-ok body (gateway HTML, proxy pages) must not
|
|
79
|
-
// be parsed as JSON nor echoed — it can be huge or carry sensitive text.
|
|
80
|
-
if (!response.ok) {
|
|
81
|
-
throw new Error(`Linear GraphQL request failed with HTTP ${String(response.status)}`);
|
|
82
|
-
}
|
|
83
|
-
const payload = (await response.json());
|
|
84
|
-
if (Array.isArray(payload.errors) && payload.errors.length > 0) {
|
|
85
|
-
throw new Error(`Linear GraphQL request failed: ${payload.errors[0]?.message ?? "unknown error"}`);
|
|
86
|
-
}
|
|
87
|
-
return payload.data ?? {};
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Resolve the internal issue id for a canonical identifier.
|
|
92
|
-
* @param context - Bound collaborators
|
|
93
|
-
* @param ref - Canonical identifier (KEY-N)
|
|
94
|
-
* @returns Internal issue id
|
|
95
|
-
*/
|
|
96
|
-
async function issueId(context, ref) {
|
|
97
|
-
const data = await context.graphql(ISSUE_ID_QUERY, { id: ref });
|
|
98
|
-
const id = data.issue?.id;
|
|
99
|
-
if (typeof id !== "string") {
|
|
100
|
-
throw new Error(`Linear issue ${ref} does not exist or is inaccessible`);
|
|
101
|
-
}
|
|
102
|
-
return id;
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Fetch the vendor-neutral state snapshot for one issue.
|
|
106
|
-
* @param context - Bound collaborators
|
|
107
|
-
* @param ref - Canonical identifier
|
|
108
|
-
* @returns Item state
|
|
109
|
-
*/
|
|
110
|
-
async function fetchState(context, ref) {
|
|
111
|
-
const data = await context.graphql(ISSUE_STATE_QUERY, { id: ref });
|
|
112
|
-
const issue = data.issue;
|
|
113
|
-
if (issue === undefined) {
|
|
114
|
-
throw new Error(`Linear issue ${ref} does not exist or is inaccessible`);
|
|
115
|
-
}
|
|
116
|
-
const labels = (issue.labels?.nodes ?? []).flatMap(node => typeof node.name === "string" ? [node.name] : []);
|
|
117
|
-
const openChildren = (issue.children?.nodes ?? []).filter(node => !TERMINAL_STATE_TYPES.has(node.state?.type ?? "")).length;
|
|
118
|
-
return {
|
|
119
|
-
ref,
|
|
120
|
-
...deriveLabelState(labels, context.doneStatuses),
|
|
121
|
-
openChildren,
|
|
122
|
-
closed: TERMINAL_STATE_TYPES.has(issue.state?.type ?? ""),
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Add the done label to the issue (labels binding).
|
|
127
|
-
* @param context - Bound collaborators
|
|
128
|
-
* @param ref - Canonical identifier
|
|
129
|
-
* @param doneStatus - Target done label name
|
|
130
|
-
*/
|
|
131
|
-
async function transition(context, ref, doneStatus) {
|
|
132
|
-
const id = await issueId(context, ref);
|
|
133
|
-
const labelData = await context.graphql(LABEL_ID_QUERY, {
|
|
134
|
-
name: doneStatus,
|
|
135
|
-
});
|
|
136
|
-
const nodes = labelData.issueLabels?.nodes;
|
|
137
|
-
const labelId = Array.isArray(nodes) ? nodes[0]?.id : undefined;
|
|
138
|
-
if (typeof labelId !== "string") {
|
|
139
|
-
throw new Error(`Linear label "${doneStatus}" was not found in the workspace — create it or fix linear.labels.build.done`);
|
|
140
|
-
}
|
|
141
|
-
await context.graphql(ADD_LABEL_MUTATION, { issueId: id, labelId });
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Find-or-update the single marker-managed comment on the issue.
|
|
145
|
-
* @param context - Bound collaborators
|
|
146
|
-
* @param ref - Canonical identifier
|
|
147
|
-
* @param body - Deterministic comment body
|
|
148
|
-
* @returns Upsert outcome
|
|
149
|
-
*/
|
|
150
|
-
async function upsertComment(context, ref, body) {
|
|
151
|
-
const data = await context.graphql(COMMENTS_QUERY, { id: ref });
|
|
152
|
-
const issue = data.issue;
|
|
153
|
-
const existing = (issue?.comments?.nodes ?? []).find(node => (node.body ?? "").startsWith(DEPLOY_STATUS_SYNC_MARKER));
|
|
154
|
-
if (existing === undefined) {
|
|
155
|
-
await context.graphql(COMMENT_CREATE_MUTATION, {
|
|
156
|
-
issueId: issue?.id ?? "",
|
|
157
|
-
body,
|
|
158
|
-
});
|
|
159
|
-
return "created";
|
|
160
|
-
}
|
|
161
|
-
if (existing.body === body)
|
|
162
|
-
return "unchanged";
|
|
163
|
-
await context.graphql(COMMENT_UPDATE_MUTATION, {
|
|
164
|
-
commentId: existing.id ?? "",
|
|
165
|
-
body,
|
|
166
|
-
});
|
|
167
|
-
return "updated";
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* Close the issue by moving it to the team's completed workflow state.
|
|
171
|
-
* @param context - Bound collaborators
|
|
172
|
-
* @param ref - Canonical identifier
|
|
173
|
-
*/
|
|
174
|
-
async function closeIssue(context, ref) {
|
|
175
|
-
const data = await context.graphql(TEAM_STATES_QUERY, { id: ref });
|
|
176
|
-
const issue = data.issue;
|
|
177
|
-
const completed = (issue?.team?.states?.nodes ?? []).find(node => node.type === "completed");
|
|
178
|
-
if (completed?.id === undefined) {
|
|
179
|
-
throw new Error(`Linear team for ${ref} exposes no completed workflow state; cannot close natively`);
|
|
180
|
-
}
|
|
181
|
-
await context.graphql(ISSUE_UPDATE_STATE_MUTATION, {
|
|
182
|
-
issueId: issue?.id ?? "",
|
|
183
|
-
stateId: completed.id,
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Create the Linear adapter.
|
|
188
|
-
* @param options - Workspace and done vocabulary
|
|
189
|
-
* @param deps - Injectable fetch, env, and secret reader
|
|
190
|
-
* @returns Tracker adapter over the Linear GraphQL API
|
|
191
|
-
*/
|
|
192
|
-
export function createLinearAdapter(options, deps = {}) {
|
|
193
|
-
const context = {
|
|
194
|
-
doneStatuses: options.doneStatuses,
|
|
195
|
-
graphql: createGraphql(options.workspace, deps),
|
|
196
|
-
};
|
|
197
|
-
return {
|
|
198
|
-
fetchItemState: ref => fetchState(context, ref),
|
|
199
|
-
transitionToDone: (ref, doneStatus) => transition(context, ref, doneStatus),
|
|
200
|
-
upsertManagedComment: (ref, body) => upsertComment(context, ref, body),
|
|
201
|
-
closeNatively: ref => closeIssue(context, ref),
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
//# sourceMappingURL=deploy-status-adapter-linear.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deploy-status-adapter-linear.js","sourceRoot":"","sources":["../../src/cli/deploy-status-adapter-linear.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import type { TrackerItemState } from "../core/deploy-status-transition.js";
|
|
2
|
-
/** Result of a managed-comment upsert. */
|
|
3
|
-
export type CommentUpsertResult = "created" | "updated" | "unchanged";
|
|
4
|
-
/** Vendor adapter: dumb fetch/mutate over one tracker. */
|
|
5
|
-
export interface TrackerAdapter {
|
|
6
|
-
/** Fetch the vendor-neutral state snapshot for one item. */
|
|
7
|
-
readonly fetchItemState: (ref: string) => Promise<TrackerItemState>;
|
|
8
|
-
/** Move the item to the given config-sourced done status. */
|
|
9
|
-
readonly transitionToDone: (ref: string, doneStatus: string) => Promise<void>;
|
|
10
|
-
/** Find-or-update the single marker-managed comment on the item. */
|
|
11
|
-
readonly upsertManagedComment: (ref: string, body: string) => Promise<CommentUpsertResult>;
|
|
12
|
-
/** Close the item natively (terminal rung only; may be a vendor no-op). */
|
|
13
|
-
readonly closeNatively: (ref: string) => Promise<void>;
|
|
14
|
-
}
|
|
15
|
-
/** Executes `gh` without a shell and returns stdout. */
|
|
16
|
-
export type ExecGh = (args: readonly string[]) => Promise<string>;
|
|
17
|
-
/** Injectable collaborators for the tracker-adapter factory. */
|
|
18
|
-
export interface TrackerAdapterDeps {
|
|
19
|
-
/** gh executor (defaults to the runner from {@link createExecGh}) */
|
|
20
|
-
readonly execGh?: ExecGh;
|
|
21
|
-
/** Fetch implementation for Linear/Jira (defaults to global fetch) */
|
|
22
|
-
readonly fetchImpl?: typeof fetch;
|
|
23
|
-
/** Environment for credential sourcing (defaults to the process env) */
|
|
24
|
-
readonly env?: Record<string, string | undefined>;
|
|
25
|
-
/** Secret reader for the darwin keychain fallback */
|
|
26
|
-
readonly readSecret?: (service: string, account: string) => Promise<string | undefined>;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Build a fixed-argv executor for one executable over the shared process
|
|
30
|
-
* runner (no shell; credentials never appear in argv). Shared by the gh
|
|
31
|
-
* adapter transport and the ref-extraction git/gh deps.
|
|
32
|
-
* @param executable - Executable name resolved on PATH
|
|
33
|
-
* @param cwd - Working directory
|
|
34
|
-
* @param env - Optional environment override (tests point PATH at a fake)
|
|
35
|
-
* @returns Fixed-argv executor returning stdout
|
|
36
|
-
*/
|
|
37
|
-
export declare function createExec(executable: string, cwd: string, env?: NodeJS.ProcessEnv): (args: readonly string[]) => Promise<string>;
|
|
38
|
-
/**
|
|
39
|
-
* Build a gh executor (ambient gh auth).
|
|
40
|
-
* @param cwd - Working directory
|
|
41
|
-
* @param env - Optional environment override (tests point PATH at a fake)
|
|
42
|
-
* @returns gh executor
|
|
43
|
-
*/
|
|
44
|
-
export declare function createExecGh(cwd: string, env?: NodeJS.ProcessEnv): ExecGh;
|
|
45
|
-
/**
|
|
46
|
-
* Derive the vendor-neutral type and current status from an item's label
|
|
47
|
-
* names — shared by the label-driven adapters (GitHub, Linear). The
|
|
48
|
-
* highest-rung done label wins so at-or-beyond compares conservatively.
|
|
49
|
-
* @param labels - Label names on the item
|
|
50
|
-
* @param doneStatuses - Ladder done vocabulary, lowest rung first
|
|
51
|
-
* @returns Optional type and currentStatus fields
|
|
52
|
-
*/
|
|
53
|
-
export declare function deriveLabelState(labels: readonly string[], doneStatuses: readonly string[]): {
|
|
54
|
-
readonly type?: string;
|
|
55
|
-
readonly currentStatus?: string;
|
|
56
|
-
};
|
|
57
|
-
//# sourceMappingURL=deploy-status-adapter-shared.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deploy-status-adapter-shared.d.ts","sourceRoot":"","sources":["../../src/cli/deploy-status-adapter-shared.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAG5E,0CAA0C;AAC1C,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;AAEtE,0DAA0D;AAC1D,MAAM,WAAW,cAAc;IAC7B,4DAA4D;IAC5D,QAAQ,CAAC,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACpE,6DAA6D;IAC7D,QAAQ,CAAC,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,oEAAoE;IACpE,QAAQ,CAAC,oBAAoB,EAAE,CAC7B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAClC,2EAA2E;IAC3E,QAAQ,CAAC,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD;AAED,wDAAwD;AACxD,MAAM,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAElE,gEAAgE;AAChE,MAAM,WAAW,kBAAkB;IACjC,qEAAqE;IACrE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IAClC,wEAAwE;IACxE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAClD,qDAAqD;IACrD,QAAQ,CAAC,UAAU,CAAC,EAAE,CACpB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAClC;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CACxB,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,EACX,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,GACtB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAc9C;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAEzE;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,YAAY,EAAE,SAAS,MAAM,EAAE,GAC9B;IAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,CAS7D"}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Leaf contract module for the deploy-status-sync tracker adapters: the
|
|
3
|
-
* adapter interface, injectable-deps shape, and the executor/label helpers
|
|
4
|
-
* shared by the vendor transports. Import-graph leaf by design — the vendor
|
|
5
|
-
* adapters and the factory (`deploy-status-adapter.ts`) both import FROM
|
|
6
|
-
* here one-way, so the factory can import the vendors without a cycle
|
|
7
|
-
* (import/no-cycle). The factory re-exports this surface, so downstream
|
|
8
|
-
* importers (engine, cmd, refs, tests) are unaffected.
|
|
9
|
-
* @module cli/deploy-status-adapter-shared
|
|
10
|
-
*/
|
|
11
|
-
import { runKaneCommand } from "../core/kane-cli-process.js";
|
|
12
|
-
import { getProcessEnv } from "./update-check.js";
|
|
13
|
-
/**
|
|
14
|
-
* Build a fixed-argv executor for one executable over the shared process
|
|
15
|
-
* runner (no shell; credentials never appear in argv). Shared by the gh
|
|
16
|
-
* adapter transport and the ref-extraction git/gh deps.
|
|
17
|
-
* @param executable - Executable name resolved on PATH
|
|
18
|
-
* @param cwd - Working directory
|
|
19
|
-
* @param env - Optional environment override (tests point PATH at a fake)
|
|
20
|
-
* @returns Fixed-argv executor returning stdout
|
|
21
|
-
*/
|
|
22
|
-
export function createExec(executable, cwd, env) {
|
|
23
|
-
return async (args) => {
|
|
24
|
-
const result = await runKaneCommand(executable, [...args], {
|
|
25
|
-
cwd,
|
|
26
|
-
timeoutMs: 120_000,
|
|
27
|
-
env: env ?? getProcessEnv(),
|
|
28
|
-
});
|
|
29
|
-
if (result.exitCode !== 0) {
|
|
30
|
-
throw new Error(`${executable} ${args[0] ?? ""} failed (exit ${String(result.exitCode)}): ${result.stderr.trim()}`);
|
|
31
|
-
}
|
|
32
|
-
return result.stdout;
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Build a gh executor (ambient gh auth).
|
|
37
|
-
* @param cwd - Working directory
|
|
38
|
-
* @param env - Optional environment override (tests point PATH at a fake)
|
|
39
|
-
* @returns gh executor
|
|
40
|
-
*/
|
|
41
|
-
export function createExecGh(cwd, env) {
|
|
42
|
-
return createExec("gh", cwd, env);
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Derive the vendor-neutral type and current status from an item's label
|
|
46
|
-
* names — shared by the label-driven adapters (GitHub, Linear). The
|
|
47
|
-
* highest-rung done label wins so at-or-beyond compares conservatively.
|
|
48
|
-
* @param labels - Label names on the item
|
|
49
|
-
* @param doneStatuses - Ladder done vocabulary, lowest rung first
|
|
50
|
-
* @returns Optional type and currentStatus fields
|
|
51
|
-
*/
|
|
52
|
-
export function deriveLabelState(labels, doneStatuses) {
|
|
53
|
-
const type = labels.find(name => name.toLowerCase().startsWith("type:"));
|
|
54
|
-
const currentStatus = [...doneStatuses]
|
|
55
|
-
.reverse()
|
|
56
|
-
.find(status => labels.includes(status));
|
|
57
|
-
return {
|
|
58
|
-
...(type === undefined ? {} : { type }),
|
|
59
|
-
...(currentStatus === undefined ? {} : { currentStatus }),
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
//# sourceMappingURL=deploy-status-adapter-shared.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deploy-status-adapter-shared.js","sourceRoot":"","sources":["../../src/cli/deploy-status-adapter-shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAsClD;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CACxB,UAAkB,EAClB,GAAW,EACX,GAAuB;IAEvB,OAAO,KAAK,EAAC,IAAI,EAAC,EAAE;QAClB,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,UAAU,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE;YACzD,GAAG;YACH,SAAS,EAAE,OAAO;YAClB,GAAG,EAAE,GAAG,IAAI,aAAa,EAAE;SAC5B,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CACb,GAAG,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,iBAAiB,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CACnG,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC;IACvB,CAAC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,GAAuB;IAC/D,OAAO,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAyB,EACzB,YAA+B;IAE/B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;IACzE,MAAM,aAAa,GAAG,CAAC,GAAG,YAAY,CAAC;SACpC,OAAO,EAAE;SACT,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3C,OAAO;QACL,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;QACvC,GAAG,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC;KAC1D,CAAC;AACJ,CAAC"}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Vendor-neutral tracker adapter seam for the deploy-status-sync engine.
|
|
3
|
-
*
|
|
4
|
-
* Adapters are dumb fetch/mutate transports: leaf/container classification
|
|
5
|
-
* and every policy decision live in the pure planner
|
|
6
|
-
* (`core/deploy-status-transition.ts`). The dry-run wrapper is both the
|
|
7
|
-
* production `--dry-run` implementation and the unit-test write recorder —
|
|
8
|
-
* one seam, two uses — so "zero API writes" holds by construction.
|
|
9
|
-
* @module cli/deploy-status-adapter
|
|
10
|
-
*/
|
|
11
|
-
import type { Tracker } from "../core/deploy-status-sync.js";
|
|
12
|
-
import { type JsonValue } from "../sync/json-path.js";
|
|
13
|
-
import { type TrackerAdapter, type TrackerAdapterDeps } from "./deploy-status-adapter-shared.js";
|
|
14
|
-
export { createExec, createExecGh, deriveLabelState, } from "./deploy-status-adapter-shared.js";
|
|
15
|
-
export type { CommentUpsertResult, ExecGh, TrackerAdapter, TrackerAdapterDeps, } from "./deploy-status-adapter-shared.js";
|
|
16
|
-
/** Construction options for {@link createTrackerAdapter}. */
|
|
17
|
-
export interface TrackerAdapterOptions {
|
|
18
|
-
readonly tracker: Tracker;
|
|
19
|
-
/** Parsed `.lisa.config.json` (vendor coordinates are read from it) */
|
|
20
|
-
readonly config: JsonValue;
|
|
21
|
-
/** Ladder done vocabulary, lowest rung first (config-sourced) */
|
|
22
|
-
readonly doneStatuses: readonly string[];
|
|
23
|
-
/** Working directory for gh */
|
|
24
|
-
readonly cwd: string;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Create the vendor adapter for the configured tracker.
|
|
28
|
-
* @param options - Tracker, parsed config, done vocabulary, cwd
|
|
29
|
-
* @param deps - Injectable transports (tests inject recorders)
|
|
30
|
-
* @returns The vendor adapter
|
|
31
|
-
*/
|
|
32
|
-
export declare function createTrackerAdapter(options: TrackerAdapterOptions, deps?: TrackerAdapterDeps): TrackerAdapter;
|
|
33
|
-
/** One suppressed write reported by the dry-run wrapper. */
|
|
34
|
-
export interface RecordedWrite {
|
|
35
|
-
readonly method: "transitionToDone" | "upsertManagedComment" | "closeNatively";
|
|
36
|
-
readonly ref: string;
|
|
37
|
-
readonly detail?: string;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Wrap an adapter so reads pass through and writes are reported to the
|
|
41
|
-
* caller but never executed. The caller owns accumulation (the CLI prints
|
|
42
|
-
* planned writes as they occur; tests collect them), keeping this wrapper
|
|
43
|
-
* stateless. Used for `--dry-run` and as the unit-test write recorder.
|
|
44
|
-
* @param inner - Real adapter (only its reads are used)
|
|
45
|
-
* @param onWrite - Sink invoked once per suppressed write, in call order
|
|
46
|
-
* @returns Wrapped adapter with all writes suppressed
|
|
47
|
-
*/
|
|
48
|
-
export declare function withDryRun(inner: Pick<TrackerAdapter, "fetchItemState">, onWrite: (write: RecordedWrite) => void): TrackerAdapter;
|
|
49
|
-
//# sourceMappingURL=deploy-status-adapter.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deploy-status-adapter.d.ts","sourceRoot":"","sources":["../../src/cli/deploy-status-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAIjE,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACxB,MAAM,mCAAmC,CAAC;AAK3C,OAAO,EACL,UAAU,EACV,YAAY,EACZ,gBAAgB,GACjB,MAAM,mCAAmC,CAAC;AAC3C,YAAY,EACV,mBAAmB,EACnB,MAAM,EACN,cAAc,EACd,kBAAkB,GACnB,MAAM,mCAAmC,CAAC;AAE3C,6DAA6D;AAC7D,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,uEAAuE;IACvE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,iEAAiE;IACjE,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,+BAA+B;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAgCD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,qBAAqB,EAC9B,IAAI,GAAE,kBAAuB,GAC5B,cAAc,CA8BhB;AAED,4DAA4D;AAC5D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EACX,kBAAkB,GAClB,sBAAsB,GACtB,eAAe,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,IAAI,CAAC,cAAc,EAAE,gBAAgB,CAAC,EAC7C,OAAO,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GACtC,cAAc,CAgBhB"}
|