@codyswann/lisa 2.293.0 → 2.294.0

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.
Files changed (123) hide show
  1. package/all/copy-overwrite/scripts/lisa-work-item.mjs +12 -3
  2. package/dist/cli/deploy-status-adapter-github.d.ts +20 -0
  3. package/dist/cli/deploy-status-adapter-github.d.ts.map +1 -0
  4. package/dist/cli/deploy-status-adapter-github.js +167 -0
  5. package/dist/cli/deploy-status-adapter-github.js.map +1 -0
  6. package/dist/cli/deploy-status-adapter-jira.d.ts +18 -0
  7. package/dist/cli/deploy-status-adapter-jira.d.ts.map +1 -0
  8. package/dist/cli/deploy-status-adapter-jira.js +215 -0
  9. package/dist/cli/deploy-status-adapter-jira.js.map +1 -0
  10. package/dist/cli/deploy-status-adapter-linear.d.ts +16 -0
  11. package/dist/cli/deploy-status-adapter-linear.d.ts.map +1 -0
  12. package/dist/cli/deploy-status-adapter-linear.js +204 -0
  13. package/dist/cli/deploy-status-adapter-linear.js.map +1 -0
  14. package/dist/cli/deploy-status-adapter-shared.d.ts +57 -0
  15. package/dist/cli/deploy-status-adapter-shared.d.ts.map +1 -0
  16. package/dist/cli/deploy-status-adapter-shared.js +62 -0
  17. package/dist/cli/deploy-status-adapter-shared.js.map +1 -0
  18. package/dist/cli/deploy-status-adapter.d.ts +49 -0
  19. package/dist/cli/deploy-status-adapter.d.ts.map +1 -0
  20. package/dist/cli/deploy-status-adapter.js +87 -0
  21. package/dist/cli/deploy-status-adapter.js.map +1 -0
  22. package/dist/cli/deploy-status-refs.d.ts +70 -0
  23. package/dist/cli/deploy-status-refs.d.ts.map +1 -0
  24. package/dist/cli/deploy-status-refs.js +195 -0
  25. package/dist/cli/deploy-status-refs.js.map +1 -0
  26. package/dist/cli/deploy-status-sync-cmd.d.ts +23 -0
  27. package/dist/cli/deploy-status-sync-cmd.d.ts.map +1 -0
  28. package/dist/cli/deploy-status-sync-cmd.js +75 -0
  29. package/dist/cli/deploy-status-sync-cmd.js.map +1 -0
  30. package/dist/cli/deploy-status-sync-engine.d.ts +49 -0
  31. package/dist/cli/deploy-status-sync-engine.d.ts.map +1 -0
  32. package/dist/cli/deploy-status-sync-engine.js +214 -0
  33. package/dist/cli/deploy-status-sync-engine.js.map +1 -0
  34. package/dist/cli/deploy-status-sync-exec.d.ts +73 -0
  35. package/dist/cli/deploy-status-sync-exec.d.ts.map +1 -0
  36. package/dist/cli/deploy-status-sync-exec.js +95 -0
  37. package/dist/cli/deploy-status-sync-exec.js.map +1 -0
  38. package/dist/cli/gate-commands.d.ts +3 -1
  39. package/dist/cli/gate-commands.d.ts.map +1 -1
  40. package/dist/cli/gate-commands.js +26 -0
  41. package/dist/cli/gate-commands.js.map +1 -1
  42. package/dist/cli/index.d.ts +2 -7
  43. package/dist/cli/index.d.ts.map +1 -1
  44. package/dist/cli/index.js +4 -43
  45. package/dist/cli/index.js.map +1 -1
  46. package/dist/cli/kane-commands.d.ts +21 -0
  47. package/dist/cli/kane-commands.d.ts.map +1 -0
  48. package/dist/cli/kane-commands.js +44 -0
  49. package/dist/cli/kane-commands.js.map +1 -0
  50. package/dist/cli/update-check.d.ts +8 -0
  51. package/dist/cli/update-check.d.ts.map +1 -1
  52. package/dist/cli/update-check.js +4 -2
  53. package/dist/cli/update-check.js.map +1 -1
  54. package/dist/core/deploy-status-sync.d.ts +15 -0
  55. package/dist/core/deploy-status-sync.d.ts.map +1 -1
  56. package/dist/core/deploy-status-sync.js +57 -19
  57. package/dist/core/deploy-status-sync.js.map +1 -1
  58. package/dist/core/deploy-status-transition.d.ts +97 -0
  59. package/dist/core/deploy-status-transition.d.ts.map +1 -0
  60. package/dist/core/deploy-status-transition.js +134 -0
  61. package/dist/core/deploy-status-transition.js.map +1 -0
  62. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  63. package/dist/core/upstream-evidence-manifest.js +24 -3
  64. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  65. package/package.json +1 -1
  66. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  68. package/plugins/lisa/rules/eager/config-resolution.md +3 -2
  69. package/plugins/lisa/rules/reference/config-resolution.md +13 -1
  70. package/plugins/lisa-agy/plugin.json +1 -1
  71. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  73. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  74. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  75. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  76. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  77. package/plugins/lisa-copilot/rules/eager/config-resolution.md +3 -2
  78. package/plugins/lisa-copilot/rules/reference/config-resolution.md +13 -1
  79. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  80. package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +13 -1
  81. package/plugins/lisa-cursor/rules/config-resolution.mdc +3 -2
  82. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  83. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  84. package/plugins/lisa-expo-agy/plugin.json +1 -1
  85. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  86. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  87. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  88. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  89. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  90. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  91. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  92. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  93. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  94. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  95. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  96. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  97. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  98. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  99. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  100. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  101. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  102. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  103. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  104. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  105. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  106. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  107. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  108. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  109. package/plugins/lisa-rails-agy/plugin.json +1 -1
  110. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  111. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  112. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  113. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  114. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  115. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  116. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  117. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  118. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  119. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  120. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  121. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  122. package/plugins/src/base/rules/eager/config-resolution.md +3 -2
  123. package/plugins/src/base/rules/reference/config-resolution.md +13 -1
@@ -0,0 +1,204 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy-status-adapter-linear.js","sourceRoot":"","sources":["../../src/cli/deploy-status-adapter-linear.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,62 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,49 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,87 @@
1
+ import { getAtPath } from "../sync/json-path.js";
2
+ import { createGithubAdapter } from "./deploy-status-adapter-github.js";
3
+ import { createJiraAdapter } from "./deploy-status-adapter-jira.js";
4
+ import { createLinearAdapter } from "./deploy-status-adapter-linear.js";
5
+ import { createExecGh, } from "./deploy-status-adapter-shared.js";
6
+ // Shared adapter surface lives in the leaf contract module (cycle-free:
7
+ // the vendor adapters import it directly); re-exported here so downstream
8
+ // importers (engine, cmd, refs, tests) keep a single import site.
9
+ export { createExec, createExecGh, deriveLabelState, } from "./deploy-status-adapter-shared.js";
10
+ /**
11
+ * Read a required string from config, failing decision-readably.
12
+ * @param config - Parsed config
13
+ * @param dotPath - Dot path of the key
14
+ * @returns The configured string
15
+ */
16
+ function requireConfigString(config, dotPath) {
17
+ const value = getAtPath(config, dotPath);
18
+ if (typeof value !== "string" || value.length === 0) {
19
+ throw new Error(`Missing ${dotPath} in .lisa.config.json — required to reach the configured tracker`);
20
+ }
21
+ return value;
22
+ }
23
+ /**
24
+ * Read an optional string from config.
25
+ * @param config - Parsed config
26
+ * @param dotPath - Dot path of the key
27
+ * @returns The configured string, or undefined
28
+ */
29
+ function optionalConfigString(config, dotPath) {
30
+ const value = getAtPath(config, dotPath);
31
+ return typeof value === "string" && value.length > 0 ? value : undefined;
32
+ }
33
+ /**
34
+ * Create the vendor adapter for the configured tracker.
35
+ * @param options - Tracker, parsed config, done vocabulary, cwd
36
+ * @param deps - Injectable transports (tests inject recorders)
37
+ * @returns The vendor adapter
38
+ */
39
+ export function createTrackerAdapter(options, deps = {}) {
40
+ const { tracker, config, doneStatuses, cwd } = options;
41
+ if (tracker === "github") {
42
+ const org = requireConfigString(config, "github.org");
43
+ const repo = requireConfigString(config, "github.repo");
44
+ return createGithubAdapter({ repository: `${org}/${repo}`, doneStatuses }, { execGh: deps.execGh ?? createExecGh(cwd) });
45
+ }
46
+ if (tracker === "linear") {
47
+ return createLinearAdapter({
48
+ workspace: requireConfigString(config, "linear.workspace"),
49
+ doneStatuses,
50
+ }, deps);
51
+ }
52
+ const cloudId = optionalConfigString(config, "atlassian.cloudId");
53
+ const site = optionalConfigString(config, "atlassian.site");
54
+ const email = optionalConfigString(config, "atlassian.email");
55
+ return createJiraAdapter({
56
+ ...(cloudId === undefined ? {} : { cloudId }),
57
+ ...(site === undefined ? {} : { site }),
58
+ ...(email === undefined ? {} : { email }),
59
+ }, deps);
60
+ }
61
+ /**
62
+ * Wrap an adapter so reads pass through and writes are reported to the
63
+ * caller but never executed. The caller owns accumulation (the CLI prints
64
+ * planned writes as they occur; tests collect them), keeping this wrapper
65
+ * stateless. Used for `--dry-run` and as the unit-test write recorder.
66
+ * @param inner - Real adapter (only its reads are used)
67
+ * @param onWrite - Sink invoked once per suppressed write, in call order
68
+ * @returns Wrapped adapter with all writes suppressed
69
+ */
70
+ export function withDryRun(inner, onWrite) {
71
+ return {
72
+ fetchItemState: ref => inner.fetchItemState(ref),
73
+ transitionToDone: (ref, doneStatus) => {
74
+ onWrite({ method: "transitionToDone", ref, detail: doneStatus });
75
+ return Promise.resolve();
76
+ },
77
+ upsertManagedComment: (ref, body) => {
78
+ onWrite({ method: "upsertManagedComment", ref, detail: body });
79
+ return Promise.resolve("created");
80
+ },
81
+ closeNatively: ref => {
82
+ onWrite({ method: "closeNatively", ref });
83
+ return Promise.resolve();
84
+ },
85
+ };
86
+ }
87
+ //# sourceMappingURL=deploy-status-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy-status-adapter.js","sourceRoot":"","sources":["../../src/cli/deploy-status-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Work-item ref extraction for deploy-status-sync (DSS-2, AC 1).
3
+ *
4
+ * Given a `base..head` commit range: union the `Work-Item:` trailer values
5
+ * of every commit (parsed by git's own trailer engine via the
6
+ * `%(trailers:key=Work-Item,valueonly)` pretty format) with the `Refs` /
7
+ * `Closes` lines of every merged PR associated with those commits (GitHub
8
+ * associated-PRs endpoint — no search-index lag), canonicalize each token
9
+ * against the configured tracker, and dedupe on the canonical form.
10
+ * Out-of-scope tokens are skipped with a reason, never an error.
11
+ * @module cli/deploy-status-refs
12
+ */
13
+ import type { Tracker } from "../core/deploy-status-sync.js";
14
+ /** Injectable git/gh executors used by the extractor. */
15
+ export interface RefExtractionDeps {
16
+ /** Run git with fixed argv and return stdout */
17
+ readonly execGit: (args: readonly string[]) => Promise<string>;
18
+ /** Run gh with fixed argv and return stdout */
19
+ readonly execGh: (args: readonly string[]) => Promise<string>;
20
+ }
21
+ /** Extraction options. */
22
+ export interface ExtractRefsOptions {
23
+ /** Commit range in `base..head` form */
24
+ readonly range: string;
25
+ /** Tracker vendor the tokens canonicalize against */
26
+ readonly tracker: Tracker;
27
+ /** Configured `owner/repo` (binds bare `#N`; enables PR-body lookups) */
28
+ readonly repository?: string;
29
+ /** Jira project key / Linear team key for `KEY-N` canonicalization */
30
+ readonly projectKey?: string;
31
+ /** Repository working directory */
32
+ readonly cwd: string;
33
+ }
34
+ /** One out-of-scope token, reported instead of raised. */
35
+ export interface SkippedRef {
36
+ readonly token: string;
37
+ readonly reason: string;
38
+ }
39
+ /** Extraction result. */
40
+ export interface ExtractedRefs {
41
+ /** Canonical refs, deduped, in first-appearance order */
42
+ readonly refs: readonly string[];
43
+ /** Out-of-scope tokens with reasons */
44
+ readonly skipped: readonly SkippedRef[];
45
+ /** Resolved head SHA of the range */
46
+ readonly headSha: string;
47
+ }
48
+ /**
49
+ * Split items into consecutive chunks of at most `size` elements. Used to
50
+ * bound gh fan-out: chunks run sequentially, items within a chunk run
51
+ * concurrently.
52
+ * @param items - Items to split
53
+ * @param size - Maximum chunk size (must be positive)
54
+ * @returns Consecutive chunks in input order
55
+ */
56
+ export declare function chunk<T>(items: readonly T[], size: number): readonly (readonly T[])[];
57
+ /**
58
+ * Build production deps over the shared fixed-argv executor factory.
59
+ * @param cwd - Repository working directory
60
+ * @returns Real git/gh executors
61
+ */
62
+ export declare function defaultRefExtractionDeps(cwd: string): RefExtractionDeps;
63
+ /**
64
+ * Extract the deduped union of work-item refs for a commit range.
65
+ * @param options - Range, tracker scope, and working directory
66
+ * @param deps - Injectable executors (defaults to real git/gh)
67
+ * @returns Canonical refs, skipped tokens, and the resolved head SHA
68
+ */
69
+ export declare function extractWorkItemRefs(options: ExtractRefsOptions, deps?: RefExtractionDeps): Promise<ExtractedRefs>;
70
+ //# sourceMappingURL=deploy-status-refs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy-status-refs.d.ts","sourceRoot":"","sources":["../../src/cli/deploy-status-refs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAG7D,yDAAyD;AACzD,MAAM,WAAW,iBAAiB;IAChC,gDAAgD;IAChD,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,+CAA+C;IAC/C,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/D;AAED,0BAA0B;AAC1B,MAAM,WAAW,kBAAkB;IACjC,wCAAwC;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,yEAAyE;IACzE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,sEAAsE;IACtE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,mCAAmC;IACnC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,0DAA0D;AAC1D,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,yBAAyB;AACzB,MAAM,WAAW,aAAa;IAC5B,yDAAyD;IACzD,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,uCAAuC;IACvC,QAAQ,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,CAAC;IACxC,qCAAqC;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AASD;;;;;;;GAOG;AACH,wBAAgB,KAAK,CAAC,CAAC,EACrB,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,IAAI,EAAE,MAAM,GACX,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAI3B;AAWD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAKvE;AA6ID;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,kBAAkB,EAC3B,IAAI,GAAE,iBAAyD,GAC9D,OAAO,CAAC,aAAa,CAAC,CA6ExB"}