isthmus-cli 0.5.0 → 0.6.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 (80) hide show
  1. package/README.ko.md +49 -28
  2. package/README.md +55 -31
  3. package/Skills/isthmus/SKILL.md +93 -4
  4. package/dist/cli/command-support.d.ts +1 -1
  5. package/dist/cli/command-support.js +2 -2
  6. package/dist/cli/command-support.js.map +1 -1
  7. package/dist/cli/impact-command.d.ts +5 -0
  8. package/dist/cli/impact-command.js +111 -0
  9. package/dist/cli/impact-command.js.map +1 -0
  10. package/dist/cli/main.js +15 -0
  11. package/dist/cli/main.js.map +1 -1
  12. package/dist/cli/preflight-command.d.ts +5 -0
  13. package/dist/cli/preflight-command.js +83 -0
  14. package/dist/cli/preflight-command.js.map +1 -0
  15. package/dist/cli/runtime-command.d.ts +5 -0
  16. package/dist/cli/runtime-command.js +42 -0
  17. package/dist/cli/runtime-command.js.map +1 -0
  18. package/dist/cli/runtime-json-reader.d.ts +12 -0
  19. package/dist/cli/runtime-json-reader.js +37 -0
  20. package/dist/cli/runtime-json-reader.js.map +1 -0
  21. package/dist/exchange/impact-selection.d.ts +13 -0
  22. package/dist/exchange/impact-selection.js +35 -0
  23. package/dist/exchange/impact-selection.js.map +1 -0
  24. package/dist/exchange/kartograph-impact.d.ts +4 -0
  25. package/dist/exchange/kartograph-impact.js +169 -0
  26. package/dist/exchange/kartograph-impact.js.map +1 -0
  27. package/dist/exchange/messages.d.ts +51 -0
  28. package/dist/exchange/messages.js +126 -0
  29. package/dist/exchange/messages.js.map +1 -0
  30. package/dist/exchange/parse.d.ts +8 -0
  31. package/dist/exchange/parse.js +12 -8
  32. package/dist/exchange/parse.js.map +1 -1
  33. package/dist/exchange/preflight-context.d.ts +71 -0
  34. package/dist/exchange/preflight-context.js +317 -0
  35. package/dist/exchange/preflight-context.js.map +1 -0
  36. package/dist/exchange/producer-impact.d.ts +17 -0
  37. package/dist/exchange/producer-impact.js +226 -0
  38. package/dist/exchange/producer-impact.js.map +1 -0
  39. package/dist/exchange/runtime.d.ts +69 -0
  40. package/dist/exchange/runtime.js +160 -0
  41. package/dist/exchange/runtime.js.map +1 -0
  42. package/dist/join/message-address.d.ts +7 -0
  43. package/dist/join/message-address.js +37 -0
  44. package/dist/join/message-address.js.map +1 -0
  45. package/dist/join/messages.d.ts +23 -0
  46. package/dist/join/messages.js +80 -0
  47. package/dist/join/messages.js.map +1 -0
  48. package/dist/report/diff.js +4 -3
  49. package/dist/report/diff.js.map +1 -1
  50. package/dist/report/impact.d.ts +62 -0
  51. package/dist/report/impact.js +168 -0
  52. package/dist/report/impact.js.map +1 -0
  53. package/dist/report/preflight-runtime.d.ts +42 -0
  54. package/dist/report/preflight-runtime.js +193 -0
  55. package/dist/report/preflight-runtime.js.map +1 -0
  56. package/dist/report/preflight-view.d.ts +146 -0
  57. package/dist/report/preflight-view.js +189 -0
  58. package/dist/report/preflight-view.js.map +1 -0
  59. package/dist/report/preflight.d.ts +104 -0
  60. package/dist/report/preflight.js +296 -0
  61. package/dist/report/preflight.js.map +1 -0
  62. package/dist/report/runtime-impact.d.ts +38 -0
  63. package/dist/report/runtime-impact.js +94 -0
  64. package/dist/report/runtime-impact.js.map +1 -0
  65. package/dist/report/runtime.d.ts +54 -0
  66. package/dist/report/runtime.js +137 -0
  67. package/dist/report/runtime.js.map +1 -0
  68. package/dist/report/sorted-json.d.ts +1 -1
  69. package/dist/report/sorted-json.js +2 -2
  70. package/dist/report/sorted-json.js.map +1 -1
  71. package/docs/BRIDGE-MESSAGES.md +102 -0
  72. package/docs/GRAPH-EXCHANGE.md +255 -0
  73. package/docs/IMPACT.md +96 -0
  74. package/docs/PREFLIGHT.md +295 -0
  75. package/docs/RUNTIME.md +172 -0
  76. package/docs/TOOLCHAIN.md +101 -0
  77. package/package.json +11 -2
  78. package/scripts/build-preflight-toolchain.mjs +186 -0
  79. package/scripts/capture-preflight.mjs +392 -0
  80. package/scripts/run-child.mjs +16 -0
@@ -0,0 +1,146 @@
1
+ import type { BridgeEndpoint, JoinLimitation } from '../join/join.ts';
2
+ import { type PreflightRelation, type PreflightReport, type PreflightSubject } from './preflight.ts';
3
+ import type { RuntimeVerificationReport } from './runtime.ts';
4
+ /** 모든 항목 수를 보존하면서 표시 항목만 제한하는 컬렉션이다. */
5
+ export interface PreflightBounded<T> {
6
+ readonly total: number;
7
+ readonly items: readonly T[];
8
+ readonly omitted: number;
9
+ }
10
+ /** 목록 소비자가 사용할 수 있는 작은 심볼 투영이다. */
11
+ export type PreflightSubjectPreview = PreflightSubject;
12
+ export interface PreflightIssuePreview {
13
+ readonly code: string;
14
+ readonly severity: 'error' | 'warning';
15
+ readonly channel: string;
16
+ readonly method?: string;
17
+ readonly message: string;
18
+ }
19
+ export interface PreflightLimitationPreview {
20
+ readonly code: string;
21
+ readonly message: string;
22
+ readonly analysis?: string;
23
+ }
24
+ export interface PreflightBridgeLimitationPreview {
25
+ readonly platform: JoinLimitation['platform'];
26
+ readonly target: JoinLimitation['target'];
27
+ readonly tool: string;
28
+ readonly message: string;
29
+ readonly channels?: PreflightBounded<string>;
30
+ }
31
+ export interface PreflightRuntimeRoutePreview {
32
+ readonly runId: string;
33
+ readonly scenario: string;
34
+ readonly platform: string;
35
+ readonly transport: string;
36
+ readonly channel: string;
37
+ readonly method?: string;
38
+ readonly instance?: string;
39
+ readonly observedCalls: number;
40
+ readonly staticStatus: string;
41
+ readonly candidateKey?: string;
42
+ }
43
+ export interface PreflightRuntimeCandidatePreview {
44
+ readonly key: string;
45
+ readonly channel: string;
46
+ readonly method?: string;
47
+ readonly transport?: 'basic-message-channel';
48
+ readonly matching?: 'literal' | 'prefix';
49
+ readonly handlerCount: number;
50
+ readonly handlersOmitted: number;
51
+ readonly handlers: PreflightBounded<BridgeEndpoint>;
52
+ }
53
+ export interface PreflightRuntimeView {
54
+ readonly aligned: boolean;
55
+ readonly verification: {
56
+ readonly status: string;
57
+ readonly scope: string;
58
+ readonly summary: RuntimeVerificationReport['summary'];
59
+ readonly declaredScenarioPlatforms: number;
60
+ readonly nonpassedChecks: PreflightBounded<PreflightRuntimeCheckPreview>;
61
+ };
62
+ readonly unobservedBoundaries: PreflightBounded<string>;
63
+ readonly uncoveredBoundaries: PreflightBounded<string>;
64
+ readonly routes: PreflightBounded<PreflightRuntimeRoutePreview>;
65
+ readonly candidates: PreflightBounded<PreflightRuntimeCandidatePreview>;
66
+ }
67
+ export interface PreflightRuntimeCheckPreview {
68
+ readonly id: string;
69
+ readonly scenario: string;
70
+ readonly platform: string;
71
+ readonly transport: string;
72
+ readonly channel: string;
73
+ readonly method?: string;
74
+ readonly instance?: string;
75
+ readonly status: string;
76
+ readonly observedCalls: number;
77
+ }
78
+ /** 원본 보고서를 변경하지 않고 정적·runtime 정보를 압축한 뷰다. */
79
+ export interface PreflightSummaryView {
80
+ readonly format: 'isthmus-preflight-summary';
81
+ readonly version: 1;
82
+ readonly project: string;
83
+ readonly revision: string;
84
+ readonly scope: PreflightReport['scope'];
85
+ readonly complete: false;
86
+ readonly status: PreflightReport['status'];
87
+ readonly summary: PreflightReport['summary'];
88
+ readonly requiresReview: boolean;
89
+ readonly roots: PreflightBounded<{
90
+ readonly subject: PreflightSubjectPreview;
91
+ readonly depth: 0;
92
+ }>;
93
+ readonly affected: PreflightBounded<{
94
+ readonly subject: PreflightSubjectPreview;
95
+ readonly depth: number;
96
+ }>;
97
+ readonly reviewFiles: PreflightBounded<string>;
98
+ readonly issues: PreflightBounded<PreflightIssuePreview>;
99
+ readonly limitations: PreflightBounded<PreflightLimitationPreview>;
100
+ readonly bridgeLimitations: PreflightBounded<PreflightBridgeLimitationPreview>;
101
+ readonly messageLimitations?: PreflightBounded<PreflightBridgeLimitationPreview>;
102
+ readonly producers: PreflightBounded<PreflightReport['producers'][number]>;
103
+ readonly runtime?: PreflightRuntimeView;
104
+ }
105
+ interface PreflightPathStep {
106
+ readonly subject: PreflightSubjectPreview;
107
+ readonly depth: number;
108
+ readonly relations: PreflightBounded<PreflightRelationPreview>;
109
+ }
110
+ type PreflightRelationPreview = {
111
+ readonly kind: 'language';
112
+ readonly analysis: string;
113
+ readonly relationships: PreflightBounded<string>;
114
+ } | Exclude<PreflightRelation, {
115
+ readonly kind: 'language';
116
+ }>;
117
+ export interface PreflightExplanationView {
118
+ readonly format: 'isthmus-preflight-explanation';
119
+ readonly version: 1;
120
+ readonly project: string;
121
+ readonly revision: string;
122
+ readonly scope: PreflightReport['scope'];
123
+ readonly complete: false;
124
+ readonly status: 'found' | 'notFound' | 'ambiguous';
125
+ readonly selector: string;
126
+ readonly summary: PreflightReport['summary'];
127
+ readonly requiresReview: boolean;
128
+ readonly issues: PreflightBounded<PreflightIssuePreview>;
129
+ readonly limitations: PreflightBounded<PreflightLimitationPreview>;
130
+ readonly bridgeLimitations: PreflightBounded<PreflightBridgeLimitationPreview>;
131
+ readonly messageLimitations?: PreflightBounded<PreflightBridgeLimitationPreview>;
132
+ readonly runtime?: PreflightRuntimeView;
133
+ readonly result?: {
134
+ readonly subject: PreflightSubjectPreview;
135
+ readonly path: readonly PreflightPathStep[];
136
+ };
137
+ readonly candidates?: PreflightBounded<{
138
+ readonly key: string;
139
+ readonly subject: PreflightSubjectPreview;
140
+ }>;
141
+ }
142
+ /** 전체 보고서에서 상태와 개수를 계산한 뒤 목록 항목만 제한한 preflight 뷰를 만든다. */
143
+ export declare function createPreflightSummary(report: PreflightReport, limit?: number): PreflightSummaryView;
144
+ /** 정확히 일치하는 심볼을 설명하고, 찾으면 root부터의 전체 경로를 제공한다. */
145
+ export declare function createPreflightExplanation(report: PreflightReport, selector: string): PreflightExplanationView;
146
+ export {};
@@ -0,0 +1,189 @@
1
+ import { compareStrings } from "../compare.js";
2
+ import { hasPreflightBlockers, PreflightGraphError } from "./preflight.js";
3
+ const VIEW_LIMIT = 20;
4
+ /** 전체 보고서에서 상태와 개수를 계산한 뒤 목록 항목만 제한한 preflight 뷰를 만든다. */
5
+ export function createPreflightSummary(report, limit = VIEW_LIMIT) {
6
+ assertLimit(limit);
7
+ const view = commonView(report, limit);
8
+ return {
9
+ format: 'isthmus-preflight-summary', version: 1,
10
+ project: report.project, revision: report.revision, scope: report.scope,
11
+ complete: false, status: report.status, summary: report.summary,
12
+ requiresReview: requiresReview(report),
13
+ roots: bounded(sortedRoots(report.roots).map((subject) => ({ subject, depth: 0 })), limit),
14
+ affected: bounded(sortedAffected(report.affected).map(({ subject, depth }) => ({ subject, depth })), limit),
15
+ ...view,
16
+ };
17
+ }
18
+ /** 정확히 일치하는 심볼을 설명하고, 찾으면 root부터의 전체 경로를 제공한다. */
19
+ export function createPreflightExplanation(report, selector) {
20
+ const limit = VIEW_LIMIT;
21
+ const view = commonView(report, limit);
22
+ const subjects = allSubjects(report);
23
+ const matches = matchingSubjects(subjects, selector);
24
+ const base = {
25
+ format: 'isthmus-preflight-explanation', version: 1,
26
+ project: report.project, revision: report.revision, scope: report.scope,
27
+ complete: false, selector, summary: report.summary,
28
+ requiresReview: requiresReview(report), ...view,
29
+ };
30
+ if (matches.length === 0)
31
+ return { ...base, status: 'notFound' };
32
+ const candidates = bounded(matches.map(({ subject }) => ({ key: subject.key, subject })), limit);
33
+ if (matches.length !== 1)
34
+ return { ...base, status: 'ambiguous', candidates };
35
+ const target = matches[0].subject;
36
+ return { ...base, status: 'found', result: { subject: target, path: pathFor(report, target.key) } };
37
+ }
38
+ function commonView(report, limit) {
39
+ return {
40
+ reviewFiles: bounded([...report.reviewFiles].sort(compareStrings), limit),
41
+ issues: bounded([...report.issues].sort(compareIssues).map(issuePreview), limit),
42
+ limitations: bounded([...report.limitations].sort(compareLimitations).map(({ code, message, analysis }) => ({
43
+ code, message, ...(analysis === undefined ? {} : { analysis }),
44
+ })), limit),
45
+ bridgeLimitations: bounded([...report.bridgeLimitations].sort(compareBridgeLimitations).map((limitation) => ({
46
+ platform: limitation.platform, target: limitation.target, tool: limitation.tool, message: limitation.message,
47
+ ...(limitation.channels === undefined ? {} : { channels: bounded([...limitation.channels].sort(compareStrings), limit) }),
48
+ })), limit),
49
+ ...(report.messageLimitations === undefined ? {} : { messageLimitations: bounded([...report.messageLimitations]
50
+ .sort(compareBridgeLimitations).map(({ platform, target, tool, message }) => ({ platform, target, tool, message })), limit) }),
51
+ producers: bounded([...report.producers].sort((a, b) => compareStrings(a.analysis, b.analysis) || compareStrings(a.platform, b.platform)), limit),
52
+ ...(report.runtime === undefined ? {} : { runtime: runtimeView(report, limit) }),
53
+ };
54
+ }
55
+ function runtimeView(report, limit) {
56
+ const runtime = report.runtime;
57
+ const checks = runtime.verification.checks.filter(({ status }) => status !== 'passed');
58
+ const pairs = new Set(runtime.verification.checks.map(({ expected }) => JSON.stringify([expected.scenario, expected.platform])));
59
+ return {
60
+ aligned: runtime.aligned,
61
+ verification: {
62
+ status: runtime.verification.status, scope: runtime.verification.scope,
63
+ summary: runtime.verification.summary,
64
+ declaredScenarioPlatforms: pairs.size,
65
+ nonpassedChecks: bounded(checks.map(runtimeCheckPreview).sort(compareRuntimeChecks), limit),
66
+ },
67
+ unobservedBoundaries: bounded([...runtime.unobservedBoundaries].sort(compareStrings), limit),
68
+ uncoveredBoundaries: bounded([...runtime.uncoveredBoundaries].sort(compareStrings), limit),
69
+ routes: bounded(runtime.routes.map(runtimeRoutePreview).sort(compareRuntimeRoutes), limit),
70
+ candidates: bounded(runtime.candidates.map((candidate) => ({
71
+ key: candidate.key, channel: candidate.channel, ...(candidate.method === undefined ? {} : { method: candidate.method }),
72
+ ...(candidate.transport === undefined ? {} : { transport: candidate.transport, matching: candidate.matching }),
73
+ handlerCount: candidate.handlers.length + candidate.handlersOmitted, handlersOmitted: candidate.handlersOmitted,
74
+ handlers: { total: candidate.handlers.length + candidate.handlersOmitted,
75
+ items: candidate.handlers.slice(0, limit),
76
+ omitted: candidate.handlers.length + candidate.handlersOmitted - Math.min(candidate.handlers.length, limit) },
77
+ })).sort((a, b) => compareStrings(a.key, b.key)), limit),
78
+ };
79
+ }
80
+ function runtimeCheckPreview(check) {
81
+ const expected = check.expected;
82
+ return {
83
+ id: expected.id, scenario: expected.scenario, platform: expected.platform,
84
+ transport: expected.transport, channel: expected.channel,
85
+ ...(expected.method === undefined ? {} : { method: expected.method }),
86
+ ...(expected.instance === undefined ? {} : { instance: expected.instance }),
87
+ status: check.status, observedCalls: check.observedCalls,
88
+ };
89
+ }
90
+ function runtimeRoutePreview(route) {
91
+ return {
92
+ runId: route.runId, scenario: route.scenario, platform: route.platform, transport: route.transport,
93
+ channel: route.channel, ...(route.method === undefined ? {} : { method: route.method }),
94
+ ...(route.instance === undefined ? {} : { instance: route.instance }),
95
+ observedCalls: route.observedCalls, staticStatus: route.staticStatus,
96
+ ...(route.candidateKey === undefined ? {} : { candidateKey: route.candidateKey }),
97
+ };
98
+ }
99
+ function issuePreview(issue) {
100
+ const route = issue.method === undefined ? issue.channel : `${issue.channel}.${issue.method}`;
101
+ const message = issue.code === 'unhandled-invocation' || issue.code === 'unhandled-invocation-unverified'
102
+ ? `No native handler was verified for ${route}.`
103
+ : issue.code === 'unregistered-channel-creation' || issue.code === 'unregistered-channel-creation-unverified'
104
+ ? `No native registration was verified for ${route}.`
105
+ : issue.code === 'registration-without-creation'
106
+ ? `Native registration has no verified channel creation for ${route}.`
107
+ : `Native handler has no verified invocation for ${route}.`;
108
+ return {
109
+ code: issue.code, severity: issue.severity, channel: issue.channel,
110
+ ...(issue.method === undefined ? {} : { method: issue.method }), message,
111
+ };
112
+ }
113
+ function pathFor(report, targetKey) {
114
+ const roots = new Map(report.roots.map((subject) => [subject.key, subject]));
115
+ const affected = new Map(report.affected.map((item) => [item.subject.key, item]));
116
+ const steps = [];
117
+ const seen = new Set();
118
+ let reachedRoot = false;
119
+ let key = targetKey;
120
+ while (key !== undefined) {
121
+ if (seen.has(key))
122
+ throw new PreflightGraphError('Preflight explanation encountered a cyclic path.');
123
+ seen.add(key);
124
+ const root = roots.get(key);
125
+ if (root !== undefined) {
126
+ steps.push({ subject: root, depth: 0, relations: bounded([], VIEW_LIMIT) });
127
+ reachedRoot = true;
128
+ break;
129
+ }
130
+ const item = affected.get(key);
131
+ if (item === undefined)
132
+ throw new PreflightGraphError('Preflight explanation refers to an unknown path node.');
133
+ steps.push({ subject: item.subject, depth: item.depth, relations: relationPreview(item.relations, VIEW_LIMIT) });
134
+ key = item.via;
135
+ }
136
+ if (!reachedRoot) {
137
+ throw new PreflightGraphError('Preflight explanation could not find a root path.');
138
+ }
139
+ return steps.reverse();
140
+ }
141
+ function relationPreview(relations, limit) {
142
+ return bounded(relations.map((relation) => relation.kind === 'language'
143
+ ? { kind: 'language', analysis: relation.analysis, relationships: bounded([...relation.relationships].sort(compareStrings), limit) }
144
+ : relation), limit);
145
+ }
146
+ function allSubjects(report) {
147
+ const values = [...report.roots, ...report.affected.map(({ subject }) => subject)];
148
+ const unique = new Map();
149
+ values.forEach((subject, index) => { if (!unique.has(subject.key))
150
+ unique.set(subject.key, { subject, index }); });
151
+ return [...unique.values()].sort((a, b) => compareStrings(a.subject.key, b.subject.key) || a.index - b.index);
152
+ }
153
+ function matchingSubjects(subjects, selector) {
154
+ const keys = subjects.filter(({ subject }) => subject.key === selector);
155
+ if (keys.length > 0)
156
+ return keys;
157
+ const ids = subjects.filter(({ subject }) => subject.kind === 'symbol' && subject.symbol.id === selector);
158
+ if (ids.length > 0)
159
+ return ids;
160
+ return subjects.filter(({ subject }) => subject.kind === 'symbol' && subject.symbol.qualifiedName === selector);
161
+ }
162
+ function sortedRoots(subjects) { return [...subjects].sort((a, b) => compareStrings(a.key, b.key)); }
163
+ function sortedAffected(affected) {
164
+ return [...affected].sort((a, b) => a.depth - b.depth || compareStrings(a.subject.key, b.subject.key));
165
+ }
166
+ function bounded(items, limit) {
167
+ return { total: items.length, items: items.slice(0, limit), omitted: Math.max(0, items.length - limit) };
168
+ }
169
+ function assertLimit(limit) {
170
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100)
171
+ throw new RangeError('Preflight view limit must be an integer from 1 to 100.');
172
+ }
173
+ function requiresReview(report) {
174
+ return hasPreflightBlockers(report);
175
+ }
176
+ function compareIssues(a, b) {
177
+ return compareStrings(a.code, b.code) || compareStrings(a.channel, b.channel) || compareStrings(a.method ?? '', b.method ?? '') || compareStrings(a.severity, b.severity);
178
+ }
179
+ function compareLimitations(a, b) {
180
+ return compareStrings(a.code, b.code) || compareStrings(a.analysis ?? '', b.analysis ?? '') || compareStrings(a.message, b.message);
181
+ }
182
+ function compareBridgeLimitations(a, b) {
183
+ return compareStrings(a.platform, b.platform) || compareStrings(a.target ?? '', b.target ?? '') || compareStrings(a.tool, b.tool) || compareStrings(a.message, b.message);
184
+ }
185
+ function compareRuntimeChecks(a, b) { return compareStrings(a.id, b.id); }
186
+ function compareRuntimeRoutes(a, b) {
187
+ return compareStrings(a.runId, b.runId) || compareStrings(a.channel, b.channel) || compareStrings(a.method ?? '', b.method ?? '') || compareStrings(a.instance ?? '', b.instance ?? '');
188
+ }
189
+ //# sourceMappingURL=preflight-view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preflight-view.js","sourceRoot":"","sources":["../../src/report/preflight-view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAA+F,MAAM,gBAAgB,CAAC;AA2IxK,MAAM,UAAU,GAAG,EAAE,CAAC;AAEtB,0DAA0D;AAC1D,MAAM,UAAU,sBAAsB,CAAC,MAAuB,EAAE,KAAK,GAAG,UAAU;IAChF,WAAW,CAAC,KAAK,CAAC,CAAC;IACnB,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACvC,OAAO;QACL,MAAM,EAAE,2BAA2B,EAAE,OAAO,EAAE,CAAC;QAC/C,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK;QACvE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO;QAC/D,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC;QACtC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAU,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC;QACnG,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC;QAC3G,GAAG,IAAI;KACR,CAAC;AACJ,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,0BAA0B,CAAC,MAAuB,EAAE,QAAgB;IAClF,MAAM,KAAK,GAAG,UAAU,CAAC;IACzB,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG;QACX,MAAM,EAAE,+BAAwC,EAAE,OAAO,EAAE,CAAU;QACrE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK;QACvE,QAAQ,EAAE,KAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO;QAC3D,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI;KAChD,CAAC;IACF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IACjE,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACjG,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;IAC9E,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC;IACnC,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;AACtG,CAAC;AAED,SAAS,UAAU,CAAC,MAAuB,EAAE,KAAa;IACxD,OAAO;QACL,WAAW,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC;QACzE,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,KAAK,CAAC;QAChF,WAAW,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;YAC1G,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;SAC/D,CAAC,CAAC,EAAE,KAAK,CAAC;QACX,iBAAiB,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YAC3G,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO;YAC5G,GAAG,CAAC,UAAU,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;SAC1H,CAAC,CAAC,EAAE,KAAK,CAAC;QACX,GAAG,CAAC,MAAM,CAAC,kBAAkB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,kBAAkB,CAAC;iBAC5G,IAAI,CAAC,wBAAwB,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;QAChI,SAAS,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,KAAK,CAAC;QACjJ,GAAG,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;KACjF,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,MAAuB,EAAE,KAAa;IACzD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAQ,CAAC;IAChC,MAAM,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;IACvF,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACjI,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,YAAY,EAAE;YACZ,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK;YACtE,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,OAAO;YACrC,yBAAyB,EAAE,KAAK,CAAC,IAAI;YACrC,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAAE,KAAK,CAAC;SAC5F;QACD,oBAAoB,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC;QAC5F,mBAAmB,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC;QAC1F,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAAE,KAAK,CAAC;QAC1F,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YACzD,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,SAAS,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC;YACvH,GAAG,CAAC,SAAS,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAS,EAAE,CAAC;YAC/G,YAAY,EAAE,SAAS,CAAC,QAAQ,CAAC,MAAM,GAAG,SAAS,CAAC,eAAe,EAAE,eAAe,EAAE,SAAS,CAAC,eAAe;YAC/G,QAAQ,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,MAAM,GAAG,SAAS,CAAC,eAAe;gBACtE,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;gBACzC,OAAO,EAAE,SAAS,CAAC,QAAQ,CAAC,MAAM,GAAG,SAAS,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE;SAChH,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC;KACzD,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAyB;IACpD,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;IAChC,OAAO;QACL,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QACzE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO;QACxD,GAAG,CAAC,QAAQ,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;QACrE,GAAG,CAAC,QAAQ,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAC3E,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,CAAC,aAAa;KACzD,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAgE;IAC3F,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS;QAClG,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;QACvF,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;QACrE,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY;QACpE,GAAG,CAAC,KAAK,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE,CAAC;KAClF,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,KAAwC;IAC5D,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;IAC9F,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,KAAK,sBAAsB,IAAI,KAAK,CAAC,IAAI,KAAK,iCAAiC;QACvG,CAAC,CAAC,sCAAsC,KAAK,GAAG;QAChD,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,+BAA+B,IAAI,KAAK,CAAC,IAAI,KAAK,0CAA0C;YAC3G,CAAC,CAAC,2CAA2C,KAAK,GAAG;YACrD,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,+BAA+B;gBAC9C,CAAC,CAAC,4DAA4D,KAAK,GAAG;gBACtE,CAAC,CAAC,iDAAiD,KAAK,GAAG,CAAC;IAClE,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO;QAClE,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO;KACzE,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,MAAuB,EAAE,SAAiB;IACzD,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAC7E,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IAClF,MAAM,KAAK,GAAwB,EAAE,CAAC;IACtC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,IAAI,GAAG,GAAuB,SAAS,CAAC;IACxC,OAAO,GAAG,KAAK,SAAS,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,mBAAmB,CAAC,kDAAkD,CAAC,CAAC;QACrG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC;YAC5E,WAAW,GAAG,IAAI,CAAC;YACnB,MAAM;QACR,CAAC;QACD,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,IAAI,KAAK,SAAS;YAAE,MAAM,IAAI,mBAAmB,CAAC,uDAAuD,CAAC,CAAC;QAC/G,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,eAAe,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC;QACjH,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;IACjB,CAAC;IACD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,mBAAmB,CAAC,mDAAmD,CAAC,CAAC;IACrF,CAAC;IACD,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC;AACzB,CAAC;AAED,SAAS,eAAe,CAAC,SAAuC,EAAE,KAAa;IAC7E,OAAO,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,UAAU;QACrE,CAAC,CAAC,EAAE,IAAI,EAAE,UAAmB,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,EAAE;QAC7I,CAAC,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;AACxB,CAAC;AAED,SAAS,WAAW,CAAC,MAAuB;IAC1C,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACnF,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwD,CAAC;IAC/E,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnH,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AAChH,CAAC;AAED,SAAS,gBAAgB,CAAC,QAAiE,EAAE,QAAgB;IAC3G,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC;IACxE,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACjC,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;IAC1G,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC;IAC/B,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC;AAClH,CAAC;AAED,SAAS,WAAW,CAAC,QAAqC,IAAwB,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACtJ,SAAS,cAAc,CAAC,QAAsC;IAC5D,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;AACzG,CAAC;AAED,SAAS,OAAO,CAAI,KAAmB,EAAE,KAAa;IACpD,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,EAAE,CAAC;AAC3G,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,GAAG;QAAE,MAAM,IAAI,UAAU,CAAC,wDAAwD,CAAC,CAAC;AAC/I,CAAC;AAED,SAAS,cAAc,CAAC,MAAuB;IAC7C,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,aAAa,CAAC,CAAoC,EAAE,CAAoC;IAC/F,OAAO,cAAc,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;AAC5K,CAAC;AACD,SAAS,kBAAkB,CAAC,CAAyC,EAAE,CAAyC;IAC9G,OAAO,cAAc,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;AACtI,CAAC;AACD,SAAS,wBAAwB,CAAC,CAAiB,EAAE,CAAiB;IACpE,OAAO,cAAc,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;AAC5K,CAAC;AACD,SAAS,oBAAoB,CAAC,CAA+B,EAAE,CAA+B,IAAY,OAAO,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAC9I,SAAS,oBAAoB,CAAC,CAA+B,EAAE,CAA+B;IAC5F,OAAO,cAAc,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;AAC1L,CAAC","sourcesContent":["import { compareStrings } from '../compare.ts';\nimport type { BridgeEndpoint, JoinLimitation } from '../join/join.ts';\nimport { hasPreflightBlockers, PreflightGraphError, type PreflightAffected, type PreflightRelation, type PreflightReport, type PreflightSubject } from './preflight.ts';\nimport type { RuntimeCheckResult } from './runtime.ts';\nimport type { RuntimeVerificationReport } from './runtime.ts';\n\n/** 모든 항목 수를 보존하면서 표시 항목만 제한하는 컬렉션이다. */\nexport interface PreflightBounded<T> {\n readonly total: number;\n readonly items: readonly T[];\n readonly omitted: number;\n}\n\n/** 목록 소비자가 사용할 수 있는 작은 심볼 투영이다. */\nexport type PreflightSubjectPreview = PreflightSubject;\n\nexport interface PreflightIssuePreview {\n readonly code: string;\n readonly severity: 'error' | 'warning';\n readonly channel: string;\n readonly method?: string;\n readonly message: string;\n}\n\nexport interface PreflightLimitationPreview {\n readonly code: string;\n readonly message: string;\n readonly analysis?: string;\n}\n\nexport interface PreflightBridgeLimitationPreview {\n readonly platform: JoinLimitation['platform'];\n readonly target: JoinLimitation['target'];\n readonly tool: string;\n readonly message: string;\n readonly channels?: PreflightBounded<string>;\n}\n\nexport interface PreflightRuntimeRoutePreview {\n readonly runId: string;\n readonly scenario: string;\n readonly platform: string;\n readonly transport: string;\n readonly channel: string;\n readonly method?: string;\n readonly instance?: string;\n readonly observedCalls: number;\n readonly staticStatus: string;\n readonly candidateKey?: string;\n}\n\nexport interface PreflightRuntimeCandidatePreview {\n readonly key: string;\n readonly channel: string;\n readonly method?: string;\n readonly transport?: 'basic-message-channel';\n readonly matching?: 'literal' | 'prefix';\n readonly handlerCount: number;\n readonly handlersOmitted: number;\n readonly handlers: PreflightBounded<BridgeEndpoint>;\n}\n\nexport interface PreflightRuntimeView {\n readonly aligned: boolean;\n readonly verification: {\n readonly status: string;\n readonly scope: string;\n readonly summary: RuntimeVerificationReport['summary'];\n readonly declaredScenarioPlatforms: number;\n readonly nonpassedChecks: PreflightBounded<PreflightRuntimeCheckPreview>;\n };\n readonly unobservedBoundaries: PreflightBounded<string>;\n readonly uncoveredBoundaries: PreflightBounded<string>;\n readonly routes: PreflightBounded<PreflightRuntimeRoutePreview>;\n readonly candidates: PreflightBounded<PreflightRuntimeCandidatePreview>;\n}\n\nexport interface PreflightRuntimeCheckPreview {\n readonly id: string;\n readonly scenario: string;\n readonly platform: string;\n readonly transport: string;\n readonly channel: string;\n readonly method?: string;\n readonly instance?: string;\n readonly status: string;\n readonly observedCalls: number;\n}\n\n/** 원본 보고서를 변경하지 않고 정적·runtime 정보를 압축한 뷰다. */\nexport interface PreflightSummaryView {\n readonly format: 'isthmus-preflight-summary';\n readonly version: 1;\n readonly project: string;\n readonly revision: string;\n readonly scope: PreflightReport['scope'];\n readonly complete: false;\n readonly status: PreflightReport['status'];\n readonly summary: PreflightReport['summary'];\n readonly requiresReview: boolean;\n readonly roots: PreflightBounded<{ readonly subject: PreflightSubjectPreview; readonly depth: 0 }>;\n readonly affected: PreflightBounded<{ readonly subject: PreflightSubjectPreview; readonly depth: number }>;\n readonly reviewFiles: PreflightBounded<string>;\n readonly issues: PreflightBounded<PreflightIssuePreview>;\n readonly limitations: PreflightBounded<PreflightLimitationPreview>;\n readonly bridgeLimitations: PreflightBounded<PreflightBridgeLimitationPreview>;\n readonly messageLimitations?: PreflightBounded<PreflightBridgeLimitationPreview>;\n readonly producers: PreflightBounded<PreflightReport['producers'][number]>;\n readonly runtime?: PreflightRuntimeView;\n}\n\ninterface PreflightPathStep {\n readonly subject: PreflightSubjectPreview;\n readonly depth: number;\n readonly relations: PreflightBounded<PreflightRelationPreview>;\n}\n\ntype PreflightRelationPreview =\n | { readonly kind: 'language'; readonly analysis: string; readonly relationships: PreflightBounded<string> }\n | Exclude<PreflightRelation, { readonly kind: 'language' }>;\n\nexport interface PreflightExplanationView {\n readonly format: 'isthmus-preflight-explanation';\n readonly version: 1;\n readonly project: string;\n readonly revision: string;\n readonly scope: PreflightReport['scope'];\n readonly complete: false;\n readonly status: 'found' | 'notFound' | 'ambiguous';\n readonly selector: string;\n readonly summary: PreflightReport['summary'];\n readonly requiresReview: boolean;\n readonly issues: PreflightBounded<PreflightIssuePreview>;\n readonly limitations: PreflightBounded<PreflightLimitationPreview>;\n readonly bridgeLimitations: PreflightBounded<PreflightBridgeLimitationPreview>;\n readonly messageLimitations?: PreflightBounded<PreflightBridgeLimitationPreview>;\n readonly runtime?: PreflightRuntimeView;\n readonly result?: { readonly subject: PreflightSubjectPreview; readonly path: readonly PreflightPathStep[] };\n readonly candidates?: PreflightBounded<{ readonly key: string; readonly subject: PreflightSubjectPreview }>;\n}\n\nconst VIEW_LIMIT = 20;\n\n/** 전체 보고서에서 상태와 개수를 계산한 뒤 목록 항목만 제한한 preflight 뷰를 만든다. */\nexport function createPreflightSummary(report: PreflightReport, limit = VIEW_LIMIT): PreflightSummaryView {\n assertLimit(limit);\n const view = commonView(report, limit);\n return {\n format: 'isthmus-preflight-summary', version: 1,\n project: report.project, revision: report.revision, scope: report.scope,\n complete: false, status: report.status, summary: report.summary,\n requiresReview: requiresReview(report),\n roots: bounded(sortedRoots(report.roots).map((subject) => ({ subject, depth: 0 as const })), limit),\n affected: bounded(sortedAffected(report.affected).map(({ subject, depth }) => ({ subject, depth })), limit),\n ...view,\n };\n}\n\n/** 정확히 일치하는 심볼을 설명하고, 찾으면 root부터의 전체 경로를 제공한다. */\nexport function createPreflightExplanation(report: PreflightReport, selector: string): PreflightExplanationView {\n const limit = VIEW_LIMIT;\n const view = commonView(report, limit);\n const subjects = allSubjects(report);\n const matches = matchingSubjects(subjects, selector);\n const base = {\n format: 'isthmus-preflight-explanation' as const, version: 1 as const,\n project: report.project, revision: report.revision, scope: report.scope,\n complete: false as const, selector, summary: report.summary,\n requiresReview: requiresReview(report), ...view,\n };\n if (matches.length === 0) return { ...base, status: 'notFound' };\n const candidates = bounded(matches.map(({ subject }) => ({ key: subject.key, subject })), limit);\n if (matches.length !== 1) return { ...base, status: 'ambiguous', candidates };\n const target = matches[0]!.subject;\n return { ...base, status: 'found', result: { subject: target, path: pathFor(report, target.key) } };\n}\n\nfunction commonView(report: PreflightReport, limit: number): Pick<PreflightSummaryView, 'reviewFiles' | 'issues' | 'limitations' | 'bridgeLimitations' | 'messageLimitations' | 'producers' | 'runtime'> {\n return {\n reviewFiles: bounded([...report.reviewFiles].sort(compareStrings), limit),\n issues: bounded([...report.issues].sort(compareIssues).map(issuePreview), limit),\n limitations: bounded([...report.limitations].sort(compareLimitations).map(({ code, message, analysis }) => ({\n code, message, ...(analysis === undefined ? {} : { analysis }),\n })), limit),\n bridgeLimitations: bounded([...report.bridgeLimitations].sort(compareBridgeLimitations).map((limitation) => ({\n platform: limitation.platform, target: limitation.target, tool: limitation.tool, message: limitation.message,\n ...(limitation.channels === undefined ? {} : { channels: bounded([...limitation.channels].sort(compareStrings), limit) }),\n })), limit),\n ...(report.messageLimitations === undefined ? {} : { messageLimitations: bounded([...report.messageLimitations]\n .sort(compareBridgeLimitations).map(({ platform, target, tool, message }) => ({ platform, target, tool, message })), limit) }),\n producers: bounded([...report.producers].sort((a, b) => compareStrings(a.analysis, b.analysis) || compareStrings(a.platform, b.platform)), limit),\n ...(report.runtime === undefined ? {} : { runtime: runtimeView(report, limit) }),\n };\n}\n\nfunction runtimeView(report: PreflightReport, limit: number): PreflightRuntimeView {\n const runtime = report.runtime!;\n const checks = runtime.verification.checks.filter(({ status }) => status !== 'passed');\n const pairs = new Set(runtime.verification.checks.map(({ expected }) => JSON.stringify([expected.scenario, expected.platform])));\n return {\n aligned: runtime.aligned,\n verification: {\n status: runtime.verification.status, scope: runtime.verification.scope,\n summary: runtime.verification.summary,\n declaredScenarioPlatforms: pairs.size,\n nonpassedChecks: bounded(checks.map(runtimeCheckPreview).sort(compareRuntimeChecks), limit),\n },\n unobservedBoundaries: bounded([...runtime.unobservedBoundaries].sort(compareStrings), limit),\n uncoveredBoundaries: bounded([...runtime.uncoveredBoundaries].sort(compareStrings), limit),\n routes: bounded(runtime.routes.map(runtimeRoutePreview).sort(compareRuntimeRoutes), limit),\n candidates: bounded(runtime.candidates.map((candidate) => ({\n key: candidate.key, channel: candidate.channel, ...(candidate.method === undefined ? {} : { method: candidate.method }),\n ...(candidate.transport === undefined ? {} : { transport: candidate.transport, matching: candidate.matching! }),\n handlerCount: candidate.handlers.length + candidate.handlersOmitted, handlersOmitted: candidate.handlersOmitted,\n handlers: { total: candidate.handlers.length + candidate.handlersOmitted,\n items: candidate.handlers.slice(0, limit),\n omitted: candidate.handlers.length + candidate.handlersOmitted - Math.min(candidate.handlers.length, limit) },\n })).sort((a, b) => compareStrings(a.key, b.key)), limit),\n };\n}\n\nfunction runtimeCheckPreview(check: RuntimeCheckResult): PreflightRuntimeCheckPreview {\n const expected = check.expected;\n return {\n id: expected.id, scenario: expected.scenario, platform: expected.platform,\n transport: expected.transport, channel: expected.channel,\n ...(expected.method === undefined ? {} : { method: expected.method }),\n ...(expected.instance === undefined ? {} : { instance: expected.instance }),\n status: check.status, observedCalls: check.observedCalls,\n };\n}\n\nfunction runtimeRoutePreview(route: NonNullable<PreflightReport['runtime']>['routes'][number]): PreflightRuntimeRoutePreview {\n return {\n runId: route.runId, scenario: route.scenario, platform: route.platform, transport: route.transport,\n channel: route.channel, ...(route.method === undefined ? {} : { method: route.method }),\n ...(route.instance === undefined ? {} : { instance: route.instance }),\n observedCalls: route.observedCalls, staticStatus: route.staticStatus,\n ...(route.candidateKey === undefined ? {} : { candidateKey: route.candidateKey }),\n };\n}\n\nfunction issuePreview(issue: PreflightReport['issues'][number]): PreflightIssuePreview {\n const route = issue.method === undefined ? issue.channel : `${issue.channel}.${issue.method}`;\n const message = issue.code === 'unhandled-invocation' || issue.code === 'unhandled-invocation-unverified'\n ? `No native handler was verified for ${route}.`\n : issue.code === 'unregistered-channel-creation' || issue.code === 'unregistered-channel-creation-unverified'\n ? `No native registration was verified for ${route}.`\n : issue.code === 'registration-without-creation'\n ? `Native registration has no verified channel creation for ${route}.`\n : `Native handler has no verified invocation for ${route}.`;\n return {\n code: issue.code, severity: issue.severity, channel: issue.channel,\n ...(issue.method === undefined ? {} : { method: issue.method }), message,\n };\n}\n\nfunction pathFor(report: PreflightReport, targetKey: string): PreflightPathStep[] {\n const roots = new Map(report.roots.map((subject) => [subject.key, subject]));\n const affected = new Map(report.affected.map((item) => [item.subject.key, item]));\n const steps: PreflightPathStep[] = [];\n const seen = new Set<string>();\n let reachedRoot = false;\n let key: string | undefined = targetKey;\n while (key !== undefined) {\n if (seen.has(key)) throw new PreflightGraphError('Preflight explanation encountered a cyclic path.');\n seen.add(key);\n const root = roots.get(key);\n if (root !== undefined) {\n steps.push({ subject: root, depth: 0, relations: bounded([], VIEW_LIMIT) });\n reachedRoot = true;\n break;\n }\n const item = affected.get(key);\n if (item === undefined) throw new PreflightGraphError('Preflight explanation refers to an unknown path node.');\n steps.push({ subject: item.subject, depth: item.depth, relations: relationPreview(item.relations, VIEW_LIMIT) });\n key = item.via;\n }\n if (!reachedRoot) {\n throw new PreflightGraphError('Preflight explanation could not find a root path.');\n }\n return steps.reverse();\n}\n\nfunction relationPreview(relations: readonly PreflightRelation[], limit: number): PreflightBounded<PreflightRelationPreview> {\n return bounded(relations.map((relation) => relation.kind === 'language'\n ? { kind: 'language' as const, analysis: relation.analysis, relationships: bounded([...relation.relationships].sort(compareStrings), limit) }\n : relation), limit);\n}\n\nfunction allSubjects(report: PreflightReport): Array<{ subject: PreflightSubject; index: number }> {\n const values = [...report.roots, ...report.affected.map(({ subject }) => subject)];\n const unique = new Map<string, { subject: PreflightSubject; index: number }>();\n values.forEach((subject, index) => { if (!unique.has(subject.key)) unique.set(subject.key, { subject, index }); });\n return [...unique.values()].sort((a, b) => compareStrings(a.subject.key, b.subject.key) || a.index - b.index);\n}\n\nfunction matchingSubjects(subjects: readonly { subject: PreflightSubject; index: number }[], selector: string): Array<{ subject: PreflightSubject; index: number }> {\n const keys = subjects.filter(({ subject }) => subject.key === selector);\n if (keys.length > 0) return keys;\n const ids = subjects.filter(({ subject }) => subject.kind === 'symbol' && subject.symbol.id === selector);\n if (ids.length > 0) return ids;\n return subjects.filter(({ subject }) => subject.kind === 'symbol' && subject.symbol.qualifiedName === selector);\n}\n\nfunction sortedRoots(subjects: readonly PreflightSubject[]): PreflightSubject[] { return [...subjects].sort((a, b) => compareStrings(a.key, b.key)); }\nfunction sortedAffected(affected: readonly PreflightAffected[]): PreflightAffected[] {\n return [...affected].sort((a, b) => a.depth - b.depth || compareStrings(a.subject.key, b.subject.key));\n}\n\nfunction bounded<T>(items: readonly T[], limit: number): PreflightBounded<T> {\n return { total: items.length, items: items.slice(0, limit), omitted: Math.max(0, items.length - limit) };\n}\n\nfunction assertLimit(limit: number): asserts limit is number {\n if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100) throw new RangeError('Preflight view limit must be an integer from 1 to 100.');\n}\n\nfunction requiresReview(report: PreflightReport): boolean {\n return hasPreflightBlockers(report);\n}\n\nfunction compareIssues(a: PreflightReport['issues'][number], b: PreflightReport['issues'][number]): number {\n return compareStrings(a.code, b.code) || compareStrings(a.channel, b.channel) || compareStrings(a.method ?? '', b.method ?? '') || compareStrings(a.severity, b.severity);\n}\nfunction compareLimitations(a: PreflightReport['limitations'][number], b: PreflightReport['limitations'][number]): number {\n return compareStrings(a.code, b.code) || compareStrings(a.analysis ?? '', b.analysis ?? '') || compareStrings(a.message, b.message);\n}\nfunction compareBridgeLimitations(a: JoinLimitation, b: JoinLimitation): number {\n return compareStrings(a.platform, b.platform) || compareStrings(a.target ?? '', b.target ?? '') || compareStrings(a.tool, b.tool) || compareStrings(a.message, b.message);\n}\nfunction compareRuntimeChecks(a: PreflightRuntimeCheckPreview, b: PreflightRuntimeCheckPreview): number { return compareStrings(a.id, b.id); }\nfunction compareRuntimeRoutes(a: PreflightRuntimeRoutePreview, b: PreflightRuntimeRoutePreview): number {\n return compareStrings(a.runId, b.runId) || compareStrings(a.channel, b.channel) || compareStrings(a.method ?? '', b.method ?? '') || compareStrings(a.instance ?? '', b.instance ?? '');\n}\n"]}
@@ -0,0 +1,104 @@
1
+ import type { ImpactSymbol, PreflightContext } from '../exchange/preflight-context.ts';
2
+ import type { BridgeEndpoint, JoinLimitation } from '../join/join.ts';
3
+ import type { BridgeTarget } from '../exchange/parse.ts';
4
+ import type { CheckIssue } from './check-report.ts';
5
+ import type { PreflightRuntimeReport } from './preflight-runtime.ts';
6
+ import type { BridgeHandlerDependency } from '../exchange/messages.ts';
7
+ import type { BridgeSymbol } from '../exchange/parse.ts';
8
+ type Language = 'dart' | 'swift' | 'kotlin';
9
+ /** 언어 심볼과 경계의 키 공간을 분리한다. 원래 producer ID는 symbol.id에 보존한다. */
10
+ export type PreflightSubject = {
11
+ readonly key: string;
12
+ readonly kind: 'symbol';
13
+ readonly platform: Language;
14
+ readonly symbol: ImpactSymbol;
15
+ } | {
16
+ readonly key: string;
17
+ readonly kind: 'bridge';
18
+ readonly target: BridgeTarget;
19
+ readonly channel: string;
20
+ readonly method?: string;
21
+ readonly transport?: 'basic-message-channel';
22
+ readonly matching?: 'literal' | 'prefix';
23
+ };
24
+ /** 실제 producer 사용 관계와 문자열 브리지 관계를 서로 다른 근거로 표시한다. */
25
+ export type PreflightRelation = {
26
+ readonly kind: 'language';
27
+ readonly analysis: string;
28
+ readonly relationships: readonly string[];
29
+ } | {
30
+ readonly kind: 'bridge-message-dependency';
31
+ readonly evidence: BridgeEndpoint;
32
+ readonly dependency: Omit<BridgeHandlerDependency, 'dispatchTargets'>;
33
+ readonly dispatchTarget?: BridgeSymbol;
34
+ } | {
35
+ readonly kind: 'bridge-handler' | 'bridge-registration' | 'bridge-invocation' | 'bridge-creation' | 'bridge-message-send' | 'bridge-message-handler';
36
+ readonly evidence: BridgeEndpoint;
37
+ };
38
+ /** 가장 가까운 변경 씨앗까지의 선행 정점을 공유해 긴 경로 복사를 피한다. */
39
+ export interface PreflightAffected {
40
+ readonly subject: PreflightSubject;
41
+ readonly depth: number;
42
+ readonly via: string;
43
+ readonly relations: readonly PreflightRelation[];
44
+ }
45
+ /** 근거를 연결할 수 없는 부분과 발생 위치다. */
46
+ export interface PreflightLimitation {
47
+ readonly code: string;
48
+ readonly message: string;
49
+ readonly analysis?: string;
50
+ readonly evidence?: BridgeEndpoint;
51
+ }
52
+ /** 언어별 영향 투영과 브리지 관계를 연결한 사전 검토 문서다. */
53
+ export interface PreflightReport {
54
+ readonly format: 'isthmus-preflight';
55
+ readonly version: 1;
56
+ readonly project: string;
57
+ readonly revision: string;
58
+ readonly scope: 'cross-language-impact';
59
+ readonly complete: false;
60
+ readonly status: 'observed' | 'unobserved' | 'noChanges';
61
+ readonly selection: PreflightContext['selection'];
62
+ readonly roots: readonly PreflightSubject[];
63
+ readonly affected: readonly PreflightAffected[];
64
+ readonly boundaries: readonly {
65
+ subject: Extract<PreflightSubject, {
66
+ kind: 'bridge';
67
+ }>;
68
+ relationship: 'consumer' | 'dependency';
69
+ callers: readonly BridgeEndpoint[];
70
+ receivers: readonly BridgeEndpoint[];
71
+ }[];
72
+ readonly reviewFiles: readonly string[];
73
+ readonly issues: readonly CheckIssue[];
74
+ readonly limitations: readonly PreflightLimitation[];
75
+ readonly bridgeLimitations: readonly JoinLimitation[];
76
+ readonly messageLimitations?: readonly JoinLimitation[];
77
+ readonly runtime?: PreflightRuntimeReport;
78
+ readonly producers: ReadonlyArray<{
79
+ analysis: string;
80
+ platform: Language;
81
+ tool: {
82
+ name: string;
83
+ version: string;
84
+ };
85
+ truncated: boolean;
86
+ }>;
87
+ readonly summary: {
88
+ selectedSymbols: number;
89
+ affectedSymbols: number;
90
+ bridgeBoundaries: number;
91
+ reviewFiles: number;
92
+ errors: number;
93
+ warnings: number;
94
+ evidenceGaps: number;
95
+ };
96
+ }
97
+ /** 잘못된 그래프 투영과 자원 상한 초과를 입력 값 없이 구분한다. */
98
+ export declare class PreflightGraphError extends Error {
99
+ }
100
+ /** 전체 언어 그래프가 아닌 producer의 영향 숲을 경계에서 연결한다. */
101
+ export declare function createPreflightReport(context: PreflightContext): PreflightReport;
102
+ /** 관찰된 영향과 "영향 없음"의 보증을 구분하며 관련 공백은 CI 검토를 요구한다. */
103
+ export declare function hasPreflightBlockers(report: PreflightReport): boolean;
104
+ export {};