@tienne/gestalt 0.88.0 → 0.90.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 (226) hide show
  1. package/CLAUDE.md +7 -2
  2. package/README.ko.md +2 -1
  3. package/README.md +3 -1
  4. package/dist/package.json +7 -4
  5. package/dist/plugin/skills/_shared/proactive-routing.md +29 -12
  6. package/dist/plugin/skills/architecture/SKILL.md +944 -0
  7. package/dist/plugin/skills/brief/SKILL.md +2 -1
  8. package/dist/plugin/skills/dispatch/SKILL.md +2 -0
  9. package/dist/plugin/skills/explain/SKILL.md +4 -2
  10. package/dist/plugin/skills/jira-create/SKILL.md +2 -0
  11. package/dist/plugin/skills/pr/SKILL.md +2 -0
  12. package/dist/plugin/skills/presentation/SKILL.md +2 -0
  13. package/dist/plugin/skills/review/SKILL.md +1 -0
  14. package/dist/plugin/skills/review-loop/SKILL.md +3 -1
  15. package/dist/plugin/skills/review-reply/SKILL.md +2 -0
  16. package/dist/plugin/skills/ship/SKILL.md +2 -2
  17. package/dist/plugin/skills/slack-send/SKILL.md +2 -0
  18. package/dist/schemas/architecture-ir.schema.json +596 -0
  19. package/dist/src/architecture/canvas-geometry.d.ts +40 -0
  20. package/dist/src/architecture/canvas-geometry.d.ts.map +1 -0
  21. package/dist/src/architecture/canvas-geometry.js +212 -0
  22. package/dist/src/architecture/canvas-geometry.js.map +1 -0
  23. package/dist/src/architecture/codeowners.d.ts +16 -0
  24. package/dist/src/architecture/codeowners.d.ts.map +1 -0
  25. package/dist/src/architecture/codeowners.js +58 -0
  26. package/dist/src/architecture/codeowners.js.map +1 -0
  27. package/dist/src/architecture/compare-layout.d.ts +27 -0
  28. package/dist/src/architecture/compare-layout.d.ts.map +1 -0
  29. package/dist/src/architecture/compare-layout.js +72 -0
  30. package/dist/src/architecture/compare-layout.js.map +1 -0
  31. package/dist/src/architecture/dataflow-layout.d.ts +29 -0
  32. package/dist/src/architecture/dataflow-layout.d.ts.map +1 -0
  33. package/dist/src/architecture/dataflow-layout.js +229 -0
  34. package/dist/src/architecture/dataflow-layout.js.map +1 -0
  35. package/dist/src/architecture/doc-fresh.d.ts +31 -0
  36. package/dist/src/architecture/doc-fresh.d.ts.map +1 -0
  37. package/dist/src/architecture/doc-fresh.js +84 -0
  38. package/dist/src/architecture/doc-fresh.js.map +1 -0
  39. package/dist/src/architecture/doc-link.d.ts +84 -0
  40. package/dist/src/architecture/doc-link.d.ts.map +1 -0
  41. package/dist/src/architecture/doc-link.js +396 -0
  42. package/dist/src/architecture/doc-link.js.map +1 -0
  43. package/dist/src/architecture/doc-routes.d.ts +39 -0
  44. package/dist/src/architecture/doc-routes.d.ts.map +1 -0
  45. package/dist/src/architecture/doc-routes.js +123 -0
  46. package/dist/src/architecture/doc-routes.js.map +1 -0
  47. package/dist/src/architecture/doc-scan.d.ts +107 -0
  48. package/dist/src/architecture/doc-scan.d.ts.map +1 -0
  49. package/dist/src/architecture/doc-scan.js +617 -0
  50. package/dist/src/architecture/doc-scan.js.map +1 -0
  51. package/dist/src/architecture/doc-stale.d.ts +32 -0
  52. package/dist/src/architecture/doc-stale.d.ts.map +1 -0
  53. package/dist/src/architecture/doc-stale.js +60 -0
  54. package/dist/src/architecture/doc-stale.js.map +1 -0
  55. package/dist/src/architecture/drilldown.d.ts +51 -0
  56. package/dist/src/architecture/drilldown.d.ts.map +1 -0
  57. package/dist/src/architecture/drilldown.js +1160 -0
  58. package/dist/src/architecture/drilldown.js.map +1 -0
  59. package/dist/src/architecture/endpoint-match.d.ts +43 -0
  60. package/dist/src/architecture/endpoint-match.d.ts.map +1 -0
  61. package/dist/src/architecture/endpoint-match.js +133 -0
  62. package/dist/src/architecture/endpoint-match.js.map +1 -0
  63. package/dist/src/architecture/flow-layout.d.ts +79 -0
  64. package/dist/src/architecture/flow-layout.d.ts.map +1 -0
  65. package/dist/src/architecture/flow-layout.js +519 -0
  66. package/dist/src/architecture/flow-layout.js.map +1 -0
  67. package/dist/src/architecture/focus.d.ts +14 -0
  68. package/dist/src/architecture/focus.d.ts.map +1 -0
  69. package/dist/src/architecture/focus.js +107 -0
  70. package/dist/src/architecture/focus.js.map +1 -0
  71. package/dist/src/architecture/global-context.d.ts +23 -0
  72. package/dist/src/architecture/global-context.d.ts.map +1 -0
  73. package/dist/src/architecture/global-context.js +67 -0
  74. package/dist/src/architecture/global-context.js.map +1 -0
  75. package/dist/src/architecture/html-client.d.ts +35 -0
  76. package/dist/src/architecture/html-client.d.ts.map +1 -0
  77. package/dist/src/architecture/html-client.js +1852 -0
  78. package/dist/src/architecture/html-client.js.map +1 -0
  79. package/dist/src/architecture/html-renderer.d.ts +22 -0
  80. package/dist/src/architecture/html-renderer.d.ts.map +1 -0
  81. package/dist/src/architecture/html-renderer.js +1290 -0
  82. package/dist/src/architecture/html-renderer.js.map +1 -0
  83. package/dist/src/architecture/html-theme.d.ts +25 -0
  84. package/dist/src/architecture/html-theme.d.ts.map +1 -0
  85. package/dist/src/architecture/html-theme.js +681 -0
  86. package/dist/src/architecture/html-theme.js.map +1 -0
  87. package/dist/src/architecture/index.d.ts +9 -0
  88. package/dist/src/architecture/index.d.ts.map +1 -0
  89. package/dist/src/architecture/index.js +9 -0
  90. package/dist/src/architecture/index.js.map +1 -0
  91. package/dist/src/architecture/ir-schema.d.ts +1832 -0
  92. package/dist/src/architecture/ir-schema.d.ts.map +1 -0
  93. package/dist/src/architecture/ir-schema.js +343 -0
  94. package/dist/src/architecture/ir-schema.js.map +1 -0
  95. package/dist/src/architecture/kind-text.d.ts +21 -0
  96. package/dist/src/architecture/kind-text.d.ts.map +1 -0
  97. package/dist/src/architecture/kind-text.js +42 -0
  98. package/dist/src/architecture/kind-text.js.map +1 -0
  99. package/dist/src/architecture/layout.d.ts +227 -0
  100. package/dist/src/architecture/layout.d.ts.map +1 -0
  101. package/dist/src/architecture/layout.js +627 -0
  102. package/dist/src/architecture/layout.js.map +1 -0
  103. package/dist/src/architecture/mcp-tool-match.d.ts +49 -0
  104. package/dist/src/architecture/mcp-tool-match.d.ts.map +1 -0
  105. package/dist/src/architecture/mcp-tool-match.js +53 -0
  106. package/dist/src/architecture/mcp-tool-match.js.map +1 -0
  107. package/dist/src/architecture/merge.d.ts +54 -0
  108. package/dist/src/architecture/merge.d.ts.map +1 -0
  109. package/dist/src/architecture/merge.js +681 -0
  110. package/dist/src/architecture/merge.js.map +1 -0
  111. package/dist/src/architecture/micro-app.d.ts +20 -0
  112. package/dist/src/architecture/micro-app.d.ts.map +1 -0
  113. package/dist/src/architecture/micro-app.js +41 -0
  114. package/dist/src/architecture/micro-app.js.map +1 -0
  115. package/dist/src/architecture/name-ref-match.d.ts +43 -0
  116. package/dist/src/architecture/name-ref-match.d.ts.map +1 -0
  117. package/dist/src/architecture/name-ref-match.js +127 -0
  118. package/dist/src/architecture/name-ref-match.js.map +1 -0
  119. package/dist/src/architecture/packs/data.d.ts +109 -0
  120. package/dist/src/architecture/packs/data.d.ts.map +1 -0
  121. package/dist/src/architecture/packs/data.js +64 -0
  122. package/dist/src/architecture/packs/data.js.map +1 -0
  123. package/dist/src/architecture/packs/generic.d.ts +47 -0
  124. package/dist/src/architecture/packs/generic.d.ts.map +1 -0
  125. package/dist/src/architecture/packs/generic.js +35 -0
  126. package/dist/src/architecture/packs/generic.js.map +1 -0
  127. package/dist/src/architecture/packs/harness.d.ts +96 -0
  128. package/dist/src/architecture/packs/harness.d.ts.map +1 -0
  129. package/dist/src/architecture/packs/harness.js +66 -0
  130. package/dist/src/architecture/packs/harness.js.map +1 -0
  131. package/dist/src/architecture/packs/index.d.ts +840 -0
  132. package/dist/src/architecture/packs/index.d.ts.map +1 -0
  133. package/dist/src/architecture/packs/index.js +87 -0
  134. package/dist/src/architecture/packs/index.js.map +1 -0
  135. package/dist/src/architecture/packs/infra.d.ts +91 -0
  136. package/dist/src/architecture/packs/infra.d.ts.map +1 -0
  137. package/dist/src/architecture/packs/infra.js +57 -0
  138. package/dist/src/architecture/packs/infra.js.map +1 -0
  139. package/dist/src/architecture/packs/knowledge.d.ts +72 -0
  140. package/dist/src/architecture/packs/knowledge.d.ts.map +1 -0
  141. package/dist/src/architecture/packs/knowledge.js +58 -0
  142. package/dist/src/architecture/packs/knowledge.js.map +1 -0
  143. package/dist/src/architecture/packs/process.d.ts +87 -0
  144. package/dist/src/architecture/packs/process.d.ts.map +1 -0
  145. package/dist/src/architecture/packs/process.js +52 -0
  146. package/dist/src/architecture/packs/process.js.map +1 -0
  147. package/dist/src/architecture/packs/render-classes.d.ts +11 -0
  148. package/dist/src/architecture/packs/render-classes.d.ts.map +1 -0
  149. package/dist/src/architecture/packs/render-classes.js +92 -0
  150. package/dist/src/architecture/packs/render-classes.js.map +1 -0
  151. package/dist/src/architecture/packs/types.d.ts +66 -0
  152. package/dist/src/architecture/packs/types.d.ts.map +1 -0
  153. package/dist/src/architecture/packs/types.js +18 -0
  154. package/dist/src/architecture/packs/types.js.map +1 -0
  155. package/dist/src/architecture/packs/web-product.d.ts +348 -0
  156. package/dist/src/architecture/packs/web-product.d.ts.map +1 -0
  157. package/dist/src/architecture/packs/web-product.js +226 -0
  158. package/dist/src/architecture/packs/web-product.js.map +1 -0
  159. package/dist/src/architecture/sequence-layout.d.ts +50 -0
  160. package/dist/src/architecture/sequence-layout.d.ts.map +1 -0
  161. package/dist/src/architecture/sequence-layout.js +140 -0
  162. package/dist/src/architecture/sequence-layout.js.map +1 -0
  163. package/dist/src/architecture/service-facts.d.ts +30 -0
  164. package/dist/src/architecture/service-facts.d.ts.map +1 -0
  165. package/dist/src/architecture/service-facts.js +88 -0
  166. package/dist/src/architecture/service-facts.js.map +1 -0
  167. package/dist/src/architecture/store.d.ts +50 -0
  168. package/dist/src/architecture/store.d.ts.map +1 -0
  169. package/dist/src/architecture/store.js +320 -0
  170. package/dist/src/architecture/store.js.map +1 -0
  171. package/dist/src/architecture/types.d.ts +400 -0
  172. package/dist/src/architecture/types.d.ts.map +1 -0
  173. package/dist/src/architecture/types.js +75 -0
  174. package/dist/src/architecture/types.js.map +1 -0
  175. package/dist/src/architecture/validator.d.ts +65 -0
  176. package/dist/src/architecture/validator.d.ts.map +1 -0
  177. package/dist/src/architecture/validator.js +1249 -0
  178. package/dist/src/architecture/validator.js.map +1 -0
  179. package/dist/src/core/errors.d.ts +4 -0
  180. package/dist/src/core/errors.d.ts.map +1 -1
  181. package/dist/src/core/errors.js +8 -0
  182. package/dist/src/core/errors.js.map +1 -1
  183. package/dist/src/core/types.d.ts +4 -0
  184. package/dist/src/core/types.d.ts.map +1 -1
  185. package/dist/src/mcp/schemas.d.ts +317 -0
  186. package/dist/src/mcp/schemas.d.ts.map +1 -1
  187. package/dist/src/mcp/schemas.js +151 -0
  188. package/dist/src/mcp/schemas.js.map +1 -1
  189. package/dist/src/mcp/server.d.ts.map +1 -1
  190. package/dist/src/mcp/server.js +7 -1
  191. package/dist/src/mcp/server.js.map +1 -1
  192. package/dist/src/mcp/tools/architecture-passthrough.d.ts +9 -0
  193. package/dist/src/mcp/tools/architecture-passthrough.d.ts.map +1 -0
  194. package/dist/src/mcp/tools/architecture-passthrough.js +587 -0
  195. package/dist/src/mcp/tools/architecture-passthrough.js.map +1 -0
  196. package/dist/src/skills/parser.d.ts.map +1 -1
  197. package/dist/src/skills/parser.js +1 -0
  198. package/dist/src/skills/parser.js.map +1 -1
  199. package/dist/src/skills/types.d.ts +4 -0
  200. package/dist/src/skills/types.d.ts.map +1 -1
  201. package/dist/src/utils/claude-projects.d.ts +19 -0
  202. package/dist/src/utils/claude-projects.d.ts.map +1 -0
  203. package/dist/src/utils/claude-projects.js +157 -0
  204. package/dist/src/utils/claude-projects.js.map +1 -0
  205. package/dist/src/utils/read-only-tools.d.ts +19 -0
  206. package/dist/src/utils/read-only-tools.d.ts.map +1 -0
  207. package/dist/src/utils/read-only-tools.js +132 -0
  208. package/dist/src/utils/read-only-tools.js.map +1 -0
  209. package/package.json +7 -4
  210. package/plugin/.codex-plugin/plugin.json +1 -1
  211. package/plugin/.mcp.json +1 -1
  212. package/plugin/mcp.json +1 -1
  213. package/plugin/skills/_shared/proactive-routing.md +29 -12
  214. package/plugin/skills/architecture/SKILL.md +944 -0
  215. package/plugin/skills/brief/SKILL.md +2 -1
  216. package/plugin/skills/dispatch/SKILL.md +2 -0
  217. package/plugin/skills/explain/SKILL.md +4 -2
  218. package/plugin/skills/jira-create/SKILL.md +2 -0
  219. package/plugin/skills/pr/SKILL.md +2 -0
  220. package/plugin/skills/presentation/SKILL.md +2 -0
  221. package/plugin/skills/review/SKILL.md +1 -0
  222. package/plugin/skills/review-loop/SKILL.md +3 -1
  223. package/plugin/skills/review-reply/SKILL.md +2 -0
  224. package/plugin/skills/ship/SKILL.md +2 -2
  225. package/plugin/skills/slack-send/SKILL.md +2 -0
  226. package/schemas/architecture-ir.schema.json +596 -0
@@ -0,0 +1,396 @@
1
+ import { docNodeId } from './doc-scan.js';
2
+ import { normalizePathTemplate } from './endpoint-match.js';
3
+ import { docPathKey } from './name-ref-match.js';
4
+ import { LEGACY_PACK_IDS } from './packs/index.js';
5
+ import { KNOWLEDGE_COVERAGE_KINDS } from './packs/knowledge.js';
6
+ const MODULE_KINDS = new Set(['service', 'micro_app', 'app_module']);
7
+ const NO_OWNER = '(담당 없음)';
8
+ /** `repo:path:line` 근거를 레포와 경로로 나눈다 */
9
+ export function splitCodeLocation(location) {
10
+ const i = location.indexOf(':');
11
+ if (i <= 0)
12
+ return undefined;
13
+ return { repo: location.slice(0, i), path: docPathKey(location.slice(i + 1)) };
14
+ }
15
+ // 패키지 루트는 src 바로 앞까지다. 모노레포 앱과 백엔드 모듈이 대부분 이 꼴이라 문서가 그 아래 파일을 가리키면 그 모듈 이야기로 본다
16
+ function packageRoot(path) {
17
+ const i = path.indexOf('/src/');
18
+ return i > 0 ? path.slice(0, i) : undefined;
19
+ }
20
+ // 폴더 하나가 모듈 수십 개를 덮으면 그 문서는 레포 전체 이야기라 모듈마다 잇지 않는다
21
+ const MAX_DIR_TARGETS = 8;
22
+ /**
23
+ * 파일이 같은 노드가 없을 때 모듈로 잇는다. 가리킨 경로를 품은 가장 깊은 패키지 루트를 먼저 본다.
24
+ * 그게 없으면 가리킨 경로가 폴더라 그 아래 패키지 루트들을 본다
25
+ */
26
+ function moduleTargets(modules, repo, path) {
27
+ const inRepo = modules.filter((m) => m.repo === repo);
28
+ const owners = inRepo
29
+ .filter((m) => path === m.root || path.startsWith(`${m.root}/`))
30
+ .sort((a, b) => b.root.length - a.root.length);
31
+ if (owners.length > 0)
32
+ return owners.filter((m) => m.root === owners[0].root).map((m) => m.node);
33
+ const under = [
34
+ ...new Set(inRepo.filter((m) => m.root.startsWith(`${path}/`)).map((m) => m.node)),
35
+ ];
36
+ return under.length <= MAX_DIR_TARGETS ? under : [];
37
+ }
38
+ /** 화면 label `[app] /route · Name`에서 라우트만 뽑는다 */
39
+ export function screenRouteOf(node) {
40
+ return /(?:^|\s)(\/\S*)/.exec(node.label)?.[1];
41
+ }
42
+ const routeKey = (route) => normalizePathTemplate(route).toLowerCase();
43
+ // `/list/:tab?`처럼 끝 파라미터를 생략할 수 있는 라우트는 생략한 꼴로도 찾을 수 있어야 한다
44
+ function routeKeys(route) {
45
+ const keys = [routeKey(route)];
46
+ let r = route.trim();
47
+ while (/\/:[A-Za-z_]\w*\?$/.test(r)) {
48
+ r = r.replace(/\/:[A-Za-z_]\w*\?$/, '');
49
+ keys.push(routeKey(r || '/'));
50
+ }
51
+ return keys;
52
+ }
53
+ // 색인은 `/info/NAVER`처럼 값을 박아 적기도 한다. 같은 자리가 코드에서 파라미터면 같은 화면으로 본다
54
+ function routeFits(indexKey, techKey) {
55
+ const a = indexKey.split('/');
56
+ const b = techKey.split('/');
57
+ return (a.length === b.length &&
58
+ b.some((s) => s === '{}') &&
59
+ b.every((s, i) => s === '{}' || s === a[i]));
60
+ }
61
+ const apiKey = (method, path) => `${method.toUpperCase()} ${normalizePathTemplate(path)}`;
62
+ /**
63
+ * 기술 그림에 문서를 엮는다. 문서가 가리킨 코드 파일, 문서가 말한 API, 화면 색인의 라우트로 잇고
64
+ * 이어진 문서만 기술 IR에 얹어 knowledge-link IR을 만든다. 잇지 못한 쪽은 신호로 돌려준다
65
+ */
66
+ export function linkDocs(tech, knowledge, scanned, options) {
67
+ const aliases = options.repoAliases ?? {};
68
+ const repoIdOf = (name) => aliases[name] ?? tech.repos.find((r) => r.name === name || r.id === name)?.id;
69
+ const fileIndex = new Map();
70
+ const modules = [];
71
+ const endpoints = new Map();
72
+ for (const n of tech.nodes) {
73
+ if (n.kind === 'endpoint') {
74
+ const sp = n.label.indexOf(' ');
75
+ if (sp > 0)
76
+ endpoints.set(apiKey(n.label.slice(0, sp), n.label.slice(sp + 1)), n.id);
77
+ }
78
+ for (const e of n.evidence) {
79
+ if (e.type !== 'code')
80
+ continue;
81
+ const loc = splitCodeLocation(e.location);
82
+ if (loc === undefined)
83
+ continue;
84
+ const key = `${loc.repo}:${loc.path}`;
85
+ fileIndex.set(key, [...(fileIndex.get(key) ?? []), n.id]);
86
+ const root = MODULE_KINDS.has(n.kind) ? packageRoot(loc.path) : undefined;
87
+ if (root !== undefined)
88
+ modules.push({ repo: loc.repo, root, node: n.id });
89
+ }
90
+ }
91
+ // 근거 파일마다 담당을 찾아 합친다. 노드에 이미 적힌 담당은 출처가 따로 있으니 그대로 둔다
92
+ const techOwners = new Map();
93
+ const docOwnerMatch = new Map();
94
+ if (options.ownersOf !== undefined) {
95
+ const nameOf = (repos, id) => repos.find((r) => r.id === id)?.name ?? id;
96
+ for (const n of tech.nodes) {
97
+ const matches = [];
98
+ for (const e of n.evidence) {
99
+ if (e.type !== 'code')
100
+ continue;
101
+ const loc = splitCodeLocation(e.location);
102
+ const m = loc && options.ownersOf(nameOf(tech.repos, loc.repo), loc.path);
103
+ if (m)
104
+ matches.push(m);
105
+ }
106
+ const merged = mergeOwners(matches);
107
+ if (merged !== undefined)
108
+ techOwners.set(n.id, merged);
109
+ }
110
+ for (const n of knowledge.nodes) {
111
+ if (n.doc === undefined || n.repo === undefined)
112
+ continue;
113
+ const m = options.ownersOf(nameOf(knowledge.repos, n.repo), n.doc.path.replace(/#.*$/, ''));
114
+ if (m !== undefined)
115
+ docOwnerMatch.set(n.id, m);
116
+ }
117
+ }
118
+ const techIds = new Set(tech.nodes.map((n) => n.id));
119
+ const knowledgeById = new Map(knowledge.nodes.map((n) => [n.id, n]));
120
+ const links = new Map();
121
+ const addLink = (doc, to, via, ref, line) => {
122
+ const key = `${doc}\u0000${to}`;
123
+ const cur = links.get(key);
124
+ if (cur === undefined) {
125
+ links.set(key, { via, refs: [ref], line });
126
+ return;
127
+ }
128
+ if (!cur.refs.some((r) => r.target === ref.target))
129
+ cur.refs.push(ref);
130
+ };
131
+ const docInfo = new Map();
132
+ const signals = {
133
+ coverage: {},
134
+ uncovered: [],
135
+ stale: [],
136
+ apiMismatches: [],
137
+ screensOnlyInCode: [],
138
+ screensOnlyInIndex: [],
139
+ links: { total: 0, broken: 0, branchOnly: 0, pinned: 0, unchecked: 0 },
140
+ linkedDocs: 0,
141
+ describes: 0,
142
+ gapsByOwner: {},
143
+ };
144
+ for (const d of scanned) {
145
+ const id = docNodeId(d.repoId, d.path);
146
+ const base = knowledgeById.get(id)?.doc ?? { path: d.path };
147
+ let broken = 0;
148
+ let unchecked = 0;
149
+ let newest;
150
+ for (const ref of d.codeRefs) {
151
+ const path = docPathKey(ref.path);
152
+ const facts = options.fileFacts?.(ref.repo, path);
153
+ if (facts === undefined)
154
+ unchecked++;
155
+ else if (!facts.exists)
156
+ broken++;
157
+ if (facts?.committedAt !== undefined && (newest === undefined || facts.committedAt > newest))
158
+ newest = facts.committedAt;
159
+ const repo = repoIdOf(ref.repo);
160
+ if (repo === undefined)
161
+ continue;
162
+ const exact = fileIndex.get(`${repo}:${path}`);
163
+ const targets = exact ?? moduleTargets(modules, repo, path);
164
+ for (const t of new Set(targets)) {
165
+ addLink(id, t, 'code-ref', {
166
+ target: `${repo}:${path}`,
167
+ verified: facts?.exists === true,
168
+ pinned: ref.pinned,
169
+ ...(facts?.committedAt !== undefined ? { committedAt: facts.committedAt } : {}),
170
+ }, ref.line);
171
+ }
172
+ }
173
+ for (const api of d.apiRefs ?? []) {
174
+ const ep = endpoints.get(apiKey(api.method, api.path));
175
+ if (ep !== undefined) {
176
+ addLink(id, ep, 'api-path', { target: apiKey(api.method, api.path), verified: true }, api.line);
177
+ }
178
+ }
179
+ const info = { ...base };
180
+ if (d.codeRefs.length > 0) {
181
+ info.links = {
182
+ total: d.codeRefs.length,
183
+ broken,
184
+ branchOnly: d.codeRefs.filter((r) => r.pinned === 'branch').length,
185
+ pinned: d.codeRefs.filter((r) => r.pinned === 'commit').length,
186
+ unchecked,
187
+ };
188
+ for (const k of ['total', 'broken', 'branchOnly', 'pinned', 'unchecked'])
189
+ signals.links[k] += info.links[k];
190
+ }
191
+ const own = info.updatedAt ?? info.committedAt;
192
+ if (own !== undefined && newest !== undefined && newest > own) {
193
+ info.staleSince = newest;
194
+ signals.stale.push({ doc: id, updatedAt: own, newestRef: newest });
195
+ }
196
+ docInfo.set(id, info);
197
+ }
198
+ // 화면 색인의 라우트와 코드의 라우트를 맞춘다. 표 한 칸에 라우트가 여럿 적힌 행도 있다
199
+ const prefixes = options.screenIndexPrefixes ?? [];
200
+ if (prefixes.length > 0) {
201
+ const techScreens = new Map();
202
+ for (const n of tech.nodes) {
203
+ if (n.kind !== 'screen')
204
+ continue;
205
+ const r = screenRouteOf(n);
206
+ if (r === undefined)
207
+ continue;
208
+ for (const k of routeKeys(r))
209
+ techScreens.set(k, [...(techScreens.get(k) ?? []), n.id]);
210
+ }
211
+ const matchedTech = new Set();
212
+ for (const n of knowledge.nodes) {
213
+ if (n.kind !== 'design_screen')
214
+ continue;
215
+ if (!prefixes.some((p) => `${n.repo}/${n.doc?.path ?? ''}`.startsWith(p)))
216
+ continue;
217
+ const routes = (n.doc?.screen?.route ?? '').match(/\/[^\s,;()]*/g) ?? [];
218
+ let hit = false;
219
+ for (const r of routes) {
220
+ const key = routeKey(r);
221
+ let found = (techScreens.get(key) ?? []).map((t) => [t, key]);
222
+ if (found.length === 0)
223
+ found = [...techScreens]
224
+ .filter(([k]) => routeFits(key, k))
225
+ .flatMap(([k, ids]) => ids.map((t) => [t, k]));
226
+ for (const [t, k] of found) {
227
+ hit = true;
228
+ matchedTech.add(t);
229
+ addLink(n.id, t, 'screen-route', { target: `route:${k}`, verified: true }, 1);
230
+ }
231
+ }
232
+ if (!hit && routes.length > 0)
233
+ signals.screensOnlyInIndex.push(n.id);
234
+ if (!docInfo.has(n.id) && n.doc !== undefined)
235
+ docInfo.set(n.id, n.doc);
236
+ }
237
+ const allTech = new Set([...techScreens.values()].flat());
238
+ signals.screensOnlyInCode = [...allTech].filter((t) => !matchedTech.has(t)).sort();
239
+ signals.screensOnlyInIndex.sort();
240
+ }
241
+ const edges = [];
242
+ const linkedDocs = new Set();
243
+ const coveredTech = new Set();
244
+ for (const [key, l] of [...links].sort(([a], [b]) => (a < b ? -1 : 1))) {
245
+ const [doc, to] = key.split('\u0000');
246
+ if (!techIds.has(to))
247
+ continue;
248
+ linkedDocs.add(doc);
249
+ coveredTech.add(to);
250
+ const src = knowledgeById.get(doc);
251
+ edges.push({
252
+ id: `desc:${doc}->${to}`,
253
+ from: doc,
254
+ to,
255
+ kind: 'describes',
256
+ evidence: [
257
+ {
258
+ type: 'doc',
259
+ location: `${src?.repo ?? 'kb'}:${(src?.doc?.path ?? doc).replace(/#.*$/, '')}:${l.line}`,
260
+ visibility: 'private',
261
+ },
262
+ ],
263
+ lineStyle: 'dashed',
264
+ docLink: { via: l.via, refs: l.refs.sort((a, b) => (a.target < b.target ? -1 : 1)) },
265
+ });
266
+ }
267
+ // 문서가 말한 API가 그림에 없는지는 이 그림에 이어진 문서만 본다. 안 이어진 문서까지 세면 다른 서버 이야기가 다 어긋남이 된다
268
+ const firstTarget = new Map();
269
+ for (const e of edges)
270
+ if (!firstTarget.has(e.from))
271
+ firstTarget.set(e.from, e.to);
272
+ const unresolved = [];
273
+ const docNodes = [];
274
+ const nameOf = (n, id) => n?.displayName ?? n?.label ?? id;
275
+ for (const doc of [...linkedDocs].sort()) {
276
+ const src = knowledgeById.get(doc);
277
+ if (src === undefined)
278
+ continue;
279
+ const { parent: _parent, ...rest } = src;
280
+ const info = docInfo.get(doc) ?? src.doc;
281
+ const owners = rest.owners ?? docOwnerMatch.get(doc)?.owners;
282
+ docNodes.push({
283
+ ...rest,
284
+ ...(info !== undefined ? { doc: info } : {}),
285
+ ...(owners !== undefined ? { owners } : {}),
286
+ });
287
+ const subject = firstTarget.get(doc);
288
+ const gaps = info?.gaps ?? [];
289
+ const gapN = gaps.filter((g) => g.kind === 'gap').length;
290
+ const unvN = gaps.length - gapN;
291
+ if (gaps.length > 0) {
292
+ unresolved.push({
293
+ id: `doc-gap:${doc}`,
294
+ subject: { nodeId: subject },
295
+ question: `"${nameOf(src, doc)}" 문서에 ` +
296
+ [
297
+ gapN > 0 ? `비었다고 적힌 곳 ${gapN}개` : '',
298
+ unvN > 0 ? `확인 안 된 서술 ${unvN}개` : '',
299
+ ]
300
+ .filter(Boolean)
301
+ .join(', ') +
302
+ '가 남아 있어요. 채울 수 있나요?',
303
+ });
304
+ }
305
+ const scan = scanned.find((s) => docNodeId(s.repoId, s.path) === doc);
306
+ for (const api of scan?.apiRefs ?? []) {
307
+ const k = apiKey(api.method, api.path);
308
+ if (endpoints.has(k))
309
+ continue;
310
+ signals.apiMismatches.push({ doc, api: k, line: api.line });
311
+ unresolved.push({
312
+ id: `doc-api:${doc}:${k}`,
313
+ subject: { nodeId: subject },
314
+ question: `"${nameOf(src, doc)}" 문서가 말하는 ${k}를 이 그림의 엔드포인트에서 못 찾았어요. 바뀌었거나 다른 서버 것인가요?`,
315
+ });
316
+ }
317
+ }
318
+ for (const kind of KNOWLEDGE_COVERAGE_KINDS) {
319
+ const all = tech.nodes.filter((n) => n.kind === kind);
320
+ if (all.length === 0)
321
+ continue;
322
+ signals.coverage[kind] = {
323
+ total: all.length,
324
+ covered: all.filter((n) => coveredTech.has(n.id)).length,
325
+ };
326
+ for (const n of all)
327
+ if (!coveredTech.has(n.id))
328
+ signals.uncovered.push(n.id);
329
+ }
330
+ signals.uncovered.sort();
331
+ // 채울 사람을 찾는 신호라 그림에 이어졌는지와 상관없이 문서 전체의 구멍을 센다
332
+ for (const n of knowledge.nodes) {
333
+ if (n.kind !== 'document')
334
+ continue;
335
+ for (const g of (docInfo.get(n.id) ?? n.doc)?.gaps ?? []) {
336
+ const who = g.owner ?? docOwnerMatch.get(n.id)?.owners.join(', ') ?? NO_OWNER;
337
+ signals.gapsByOwner[who] = (signals.gapsByOwner[who] ?? 0) + 1;
338
+ }
339
+ }
340
+ if (options.ownersOf !== undefined) {
341
+ const slots = tech.nodes.filter((n) => KNOWLEDGE_COVERAGE_KINDS.includes(n.kind));
342
+ // 화면 색인은 한 파일이 행마다 노드가 되고 폴더 묶음은 문서가 아니라서 문서 파일만 센다
343
+ const docs = knowledge.nodes.filter((n) => n.kind === 'document');
344
+ const count = (ids, owned, preset) => ({
345
+ total: ids.length,
346
+ owned: ids.filter((id) => preset.has(id) || owned.has(id)).length,
347
+ catchAllOnly: ids.filter((id) => !preset.has(id) && owned.get(id)?.catchAll === true).length,
348
+ });
349
+ const presetOf = (nodes) => new Set(nodes.filter((n) => (n.owners ?? []).length > 0).map((n) => n.id));
350
+ signals.ownership = {
351
+ tech: count(slots.map((n) => n.id), techOwners, presetOf(slots)),
352
+ docs: count(docs.map((n) => n.id), docOwnerMatch, presetOf(docs)),
353
+ unownedTech: slots
354
+ .filter((n) => (n.owners ?? []).length === 0 && !techOwners.has(n.id))
355
+ .map((n) => n.id)
356
+ .sort(),
357
+ };
358
+ }
359
+ signals.linkedDocs = linkedDocs.size;
360
+ signals.describes = edges.length;
361
+ const knowledgeRepos = knowledge.repos.filter((r) => !tech.repos.some((t) => t.id === r.id));
362
+ const byId = (a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
363
+ return {
364
+ ir: {
365
+ ...tech,
366
+ view: 'knowledge-link',
367
+ packs: [...new Set([...(tech.packs ?? LEGACY_PACK_IDS), 'knowledge'])],
368
+ repos: [...tech.repos, ...knowledgeRepos],
369
+ nodes: [
370
+ ...tech.nodes.map((n) => {
371
+ const m = techOwners.get(n.id);
372
+ return m !== undefined && n.owners === undefined ? { ...n, owners: m.owners } : n;
373
+ }),
374
+ ...docNodes,
375
+ ].sort(byId),
376
+ edges: [...tech.edges, ...edges].sort(byId),
377
+ unresolved: [...tech.unresolved, ...unresolved.sort(byId)],
378
+ generatedAt: options.generatedAt,
379
+ },
380
+ signals,
381
+ docInfo,
382
+ docOwners: new Map([...docOwnerMatch].map(([id, m]) => [id, m.owners])),
383
+ };
384
+ }
385
+ // 근거 파일마다 담당이 다르면 모두 싣는다. 실제 담당이 하나라도 있으면 기본 담당은 뺀다
386
+ function mergeOwners(matches) {
387
+ if (matches.length === 0)
388
+ return undefined;
389
+ const real = matches.filter((m) => !m.catchAll);
390
+ const pick = real.length > 0 ? real : matches;
391
+ return {
392
+ owners: [...new Set(pick.flatMap((m) => m.owners))].sort(),
393
+ catchAll: real.length === 0,
394
+ };
395
+ }
396
+ //# sourceMappingURL=doc-link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doc-link.js","sourceRoot":"","sources":["../../../src/architecture/doc-link.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AA+DhE,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC;AACrE,MAAM,QAAQ,GAAG,SAAS,CAAC;AAE3B,uCAAuC;AACvC,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAC7B,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;AACjF,CAAC;AAED,gFAAgF;AAChF,SAAS,WAAW,CAAC,IAAY;IAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9C,CAAC;AAED,mDAAmD;AACnD,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B;;;GAGG;AACH,SAAS,aAAa,CACpB,OAAgE,EAChE,IAAY,EACZ,IAAY;IAEZ,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,MAAM;SAClB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;SAC/D,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACjD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAClG,MAAM,KAAK,GAAG;QACZ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;KACnF,CAAC;IACF,OAAO,KAAK,CAAC,MAAM,IAAI,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AACtD,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,aAAa,CAAC,IAAqC;IACjE,OAAO,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;AAEvF,4DAA4D;AAC5D,SAAS,SAAS,CAAC,KAAa;IAC9B,MAAM,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/B,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IACrB,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACpC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,iEAAiE;AACjE,SAAS,SAAS,CAAC,QAAgB,EAAE,OAAe;IAClD,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,OAAO,CACL,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QACrB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;QACzB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAC5C,CAAC;AACJ,CAAC;AACD,MAAM,MAAM,GAAG,CAAC,MAAc,EAAE,IAAY,EAAU,EAAE,CACtD,GAAG,MAAM,CAAC,WAAW,EAAE,IAAI,qBAAqB,CAAC,IAAI,CAAC,EAAE,CAAC;AAE3D;;;GAGG;AACH,MAAM,UAAU,QAAQ,CACtB,IAAoB,EACpB,SAAyB,EACzB,OAA8B,EAC9B,OAAwB;IAExB,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC;IAC1C,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAsB,EAAE,CACpD,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,EAAE,CAAC;IAEhF,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC9C,MAAM,OAAO,GAAmD,EAAE,CAAC;IACnE,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC1B,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAChC,IAAI,EAAE,GAAG,CAAC;gBAAE,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QACvF,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC3B,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;gBAAE,SAAS;YAChC,MAAM,GAAG,GAAG,iBAAiB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YAC1C,IAAI,GAAG,KAAK,SAAS;gBAAE,SAAS;YAChC,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YACtC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1D,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC1E,IAAI,IAAI,KAAK,SAAS;gBAAE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IAED,sDAAsD;IACtD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAsB,CAAC;IACjD,MAAM,aAAa,GAAG,IAAI,GAAG,EAAsB,CAAC;IACpD,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,CAAC,KAA8B,EAAE,EAAU,EAAE,EAAE,CAC5D,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC;QAC7C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAiB,EAAE,CAAC;YACjC,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;gBAC3B,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;oBAAE,SAAS;gBAChC,MAAM,GAAG,GAAG,iBAAiB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;gBAC1C,MAAM,CAAC,GAAG,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC1E,IAAI,CAAC;oBAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACzB,CAAC;YACD,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;YACpC,IAAI,MAAM,KAAK,SAAS;gBAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACzD,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;YAChC,IAAI,CAAC,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS;gBAAE,SAAS;YAC1D,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;YAC5F,IAAI,CAAC,KAAK,SAAS;gBAAE,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACrD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAqE,CAAC;IAC3F,MAAM,OAAO,GAAG,CAAC,GAAW,EAAE,EAAU,EAAE,GAAmB,EAAE,GAAe,EAAE,IAAY,EAAE,EAAE;QAC9F,MAAM,GAAG,GAAG,GAAG,GAAG,SAAS,EAAE,EAAE,CAAC;QAChC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC3B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3C,OAAO;QACT,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzE,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,IAAI,GAAG,EAAmB,CAAC;IAC3C,MAAM,OAAO,GAAyB;QACpC,QAAQ,EAAE,EAAE;QACZ,SAAS,EAAE,EAAE;QACb,KAAK,EAAE,EAAE;QACT,aAAa,EAAE,EAAE;QACjB,iBAAiB,EAAE,EAAE;QACrB,kBAAkB,EAAE,EAAE;QACtB,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE;QACtE,UAAU,EAAE,CAAC;QACb,SAAS,EAAE,CAAC;QACZ,WAAW,EAAE,EAAE;KAChB,CAAC;IAEF,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5D,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,MAA0B,CAAC;QAC/B,KAAK,MAAM,GAAG,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC7B,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAClD,IAAI,KAAK,KAAK,SAAS;gBAAE,SAAS,EAAE,CAAC;iBAChC,IAAI,CAAC,KAAK,CAAC,MAAM;gBAAE,MAAM,EAAE,CAAC;YACjC,IAAI,KAAK,EAAE,WAAW,KAAK,SAAS,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC;gBAC1F,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC;YAC7B,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,IAAI,KAAK,SAAS;gBAAE,SAAS;YACjC,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC;YAC/C,MAAM,OAAO,GAAG,KAAK,IAAI,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YAC5D,KAAK,MAAM,CAAC,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBACjC,OAAO,CACL,EAAE,EACF,CAAC,EACD,UAAU,EACV;oBACE,MAAM,EAAE,GAAG,IAAI,IAAI,IAAI,EAAE;oBACzB,QAAQ,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI;oBAChC,MAAM,EAAE,GAAG,CAAC,MAAM;oBAClB,GAAG,CAAC,KAAK,EAAE,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAChF,EACD,GAAG,CAAC,IAAI,CACT,CAAC;YACJ,CAAC;QACH,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,CAAC,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;YAClC,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;YACvD,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;gBACrB,OAAO,CACL,EAAE,EACF,EAAE,EACF,UAAU,EACV,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,EACxD,GAAG,CAAC,IAAI,CACT,CAAC;YACJ,CAAC;QACH,CAAC;QAED,MAAM,IAAI,GAAY,EAAE,GAAG,IAAI,EAAE,CAAC;QAClC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,KAAK,GAAG;gBACX,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM;gBACxB,MAAM;gBACN,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,MAAM;gBAClE,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,MAAM;gBAC9D,SAAS;aACV,CAAC;YACF,KAAK,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,CAAU;gBAC/E,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,WAAW,CAAC;QAC/C,IAAI,GAAG,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC;YAC9D,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;YACzB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QACrE,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,oDAAoD;IACpD,MAAM,QAAQ,GAAG,OAAO,CAAC,mBAAmB,IAAI,EAAE,CAAC;IACnD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,WAAW,GAAG,IAAI,GAAG,EAAoB,CAAC;QAChD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC3B,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ;gBAAE,SAAS;YAClC,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;YAC3B,IAAI,CAAC,KAAK,SAAS;gBAAE,SAAS;YAC9B,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC;gBAAE,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1F,CAAC;QACD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;QACtC,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;YAChC,IAAI,CAAC,CAAC,IAAI,KAAK,eAAe;gBAAE,SAAS;YACzC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;gBAAE,SAAS;YACpF,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;YACzE,IAAI,GAAG,GAAG,KAAK,CAAC;YAChB,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;gBACvB,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;gBACxB,IAAI,KAAK,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAU,CAAC,CAAC;gBACvE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;oBACpB,KAAK,GAAG,CAAC,GAAG,WAAW,CAAC;yBACrB,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;yBAClC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAU,CAAC,CAAC,CAAC;gBAC5D,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC;oBAC3B,GAAG,GAAG,IAAI,CAAC;oBACX,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;oBACnB,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,cAAc,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;gBAChF,CAAC;YACH,CAAC;YACD,IAAI,CAAC,GAAG,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACrE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,SAAS;gBAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;QAC1E,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1D,OAAO,CAAC,iBAAiB,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACnF,OAAO,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC;IACpC,CAAC;IAED,MAAM,KAAK,GAAuB,EAAE,CAAC;IACrC,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IACrC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IACtC,KAAK,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAqB,CAAC;QAC1D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,SAAS;QAC/B,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpB,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpB,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC;YACT,EAAE,EAAE,QAAQ,GAAG,KAAK,EAAE,EAAE;YACxB,IAAI,EAAE,GAAG;YACT,EAAE;YACF,IAAI,EAAE,WAAW;YACjB,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,KAAK;oBACX,QAAQ,EAAE,GAAG,GAAG,EAAE,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE;oBACzF,UAAU,EAAE,SAAS;iBACtB;aACF;YACD,SAAS,EAAE,QAAQ;YACnB,OAAO,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;SACrF,CAAC,CAAC;IACL,CAAC;IAED,4EAA4E;IAC5E,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC9C,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;YAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IACnF,MAAM,UAAU,GAAyB,EAAE,CAAC;IAC5C,MAAM,QAAQ,GAAuB,EAAE,CAAC;IACxC,MAAM,MAAM,GAAG,CAAC,CAA+B,EAAE,EAAU,EAAU,EAAE,CACrE,CAAC,EAAE,WAAW,IAAI,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;IACnC,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACzC,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,GAAG,KAAK,SAAS;YAAE,SAAS;QAChC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG,CAAC;QACzC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAC7D,QAAQ,CAAC,IAAI,CAAC;YACZ,GAAG,IAAI;YACP,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5C,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5C,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;QACtC,MAAM,IAAI,GAAG,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,MAAM,CAAC;QACzD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAChC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,UAAU,CAAC,IAAI,CAAC;gBACd,EAAE,EAAE,WAAW,GAAG,EAAE;gBACpB,OAAO,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE;gBAC5B,QAAQ,EACN,IAAI,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,QAAQ;oBAC5B;wBACE,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE;wBACpC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE;qBACrC;yBACE,MAAM,CAAC,OAAO,CAAC;yBACf,IAAI,CAAC,IAAI,CAAC;oBACb,qBAAqB;aACxB,CAAC,CAAC;QACL,CAAC;QACD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QACtE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,OAAO,IAAI,EAAE,EAAE,CAAC;YACtC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;YACvC,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,SAAS;YAC/B,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YAC5D,UAAU,CAAC,IAAI,CAAC;gBACd,EAAE,EAAE,WAAW,GAAG,IAAI,CAAC,EAAE;gBACzB,OAAO,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE;gBAC5B,QAAQ,EAAE,IAAI,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,aAAa,CAAC,2CAA2C;aACxF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,wBAAwB,EAAE,CAAC;QAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACtD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAC/B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG;YACvB,KAAK,EAAE,GAAG,CAAC,MAAM;YACjB,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM;SACzD,CAAC;QACF,KAAK,MAAM,CAAC,IAAI,GAAG;YAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBAAE,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IACzB,8CAA8C;IAC9C,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;QAChC,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU;YAAE,SAAS;QACpC,KAAK,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;YACzD,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC;YAC9E,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,wBAAwB,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAClF,oDAAoD;QACpD,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;QAClE,MAAM,KAAK,GAAG,CAAC,GAAa,EAAE,KAA8B,EAAE,MAAmB,EAAE,EAAE,CAAC,CAAC;YACrF,KAAK,EAAE,GAAG,CAAC,MAAM;YACjB,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM;YACjE,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,QAAQ,KAAK,IAAI,CAAC,CAAC,MAAM;SAC7F,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,CAAC,KAAyB,EAAE,EAAE,CAC7C,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7E,OAAO,CAAC,SAAS,GAAG;YAClB,IAAI,EAAE,KAAK,CACT,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EACtB,UAAU,EACV,QAAQ,CAAC,KAAK,CAAC,CAChB;YACD,IAAI,EAAE,KAAK,CACT,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EACrB,aAAa,EACb,QAAQ,CAAC,IAAI,CAAC,CACf;YACD,WAAW,EAAE,KAAK;iBACf,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;iBACrE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAChB,IAAI,EAAE;SACV,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC;IACrC,OAAO,CAAC,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC;IAEjC,MAAM,cAAc,GAAG,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7F,MAAM,IAAI,GAAG,CAA2B,CAAI,EAAE,CAAI,EAAU,EAAE,CAC5D,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,OAAO;QACL,EAAE,EAAE;YACF,GAAG,IAAI;YACP,IAAI,EAAE,gBAAgB;YACtB,KAAK,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,eAAe,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC;YACtE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,cAAc,CAAC;YACzC,KAAK,EAAE;gBACL,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;oBACtB,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBAC/B,OAAO,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBACpF,CAAC,CAAC;gBACF,GAAG,QAAQ;aACZ,CAAC,IAAI,CAAC,IAAI,CAAC;YACZ,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YAC3C,UAAU,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1D,WAAW,EAAE,OAAO,CAAC,WAAW;SACjC;QACD,OAAO;QACP,OAAO;QACP,SAAS,EAAE,IAAI,GAAG,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;KACxE,CAAC;AACJ,CAAC;AAED,oDAAoD;AACpD,SAAS,WAAW,CAAC,OAAqB;IACxC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3C,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;IAC9C,OAAO;QACL,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;QAC1D,QAAQ,EAAE,IAAI,CAAC,MAAM,KAAK,CAAC;KAC5B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,39 @@
1
+ import type { DocScanResult } from './doc-scan.js';
2
+ export interface DeadRoute {
3
+ /** `<repoId>/<path>` */
4
+ from: string;
5
+ keywords: string[];
6
+ targetPath: string;
7
+ }
8
+ export interface KeywordConflict {
9
+ keyword: string;
10
+ /** `<repoId>/<path>` */
11
+ targets: string[];
12
+ }
13
+ export interface DocRouteReport {
14
+ /** `<repoId>/<path>` */
15
+ entries: string[];
16
+ reachable: number;
17
+ /** 진입 문서에서 링크를 따라가도 안 닿는 문서. 진입 문서가 하나도 없으면 비운다 */
18
+ orphans: string[];
19
+ deadRoutes: DeadRoute[];
20
+ /** 같은 말이 다른 문서로 안내되는 자리 */
21
+ conflicts: KeywordConflict[];
22
+ /** 질문 안내 표가 이 문서로 보내는 말. 키는 `<repoId>/<path>` */
23
+ keywords: Record<string, string[]>;
24
+ }
25
+ /** 상대 링크를 레포 기준 경로로 편다. 레포 밖이나 바깥 주소면 undefined */
26
+ export declare function resolveDocLink(fromPath: string, link: string): string | undefined;
27
+ export type DocResolver = (doc: {
28
+ repoId: string;
29
+ path: string;
30
+ }, ref: string) => string | undefined;
31
+ /**
32
+ * 문서에 적힌 md 경로를 훑은 문서 하나로 푼다. 돌려주는 값은 `<repoId>/<path>`다.
33
+ * 문서 폴더 기준으로 먼저 본다. 안 맞으면 위 폴더로 한 단씩 올라가며 붙여 본다. 옆 스킬이나 레포 루트 기준으로 적은 경로가 여기서 풀린다.
34
+ * 그래도 없으면 같은 레포에서 뒷부분이 맞는 문서가 하나뿐일 때만 그 문서로 본다
35
+ */
36
+ export declare function docResolver(scan: DocScanResult): DocResolver;
37
+ /** 질문 안내 표와 문서 사이 링크로 질문 길을 따라가 고립 문서, 막다른 안내, 같은 말 충돌을 찾는다 */
38
+ export declare function analyzeDocRoutes(scan: DocScanResult): DocRouteReport;
39
+ //# sourceMappingURL=doc-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doc-routes.d.ts","sourceRoot":"","sources":["../../../src/architecture/doc-routes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAYnD,MAAM,WAAW,SAAS;IACxB,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,wBAAwB;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,wBAAwB;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,2BAA2B;IAC3B,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACpC;AAED,mDAAmD;AACnD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQjF;AAID,MAAM,MAAM,WAAW,GAAG,CACxB,GAAG,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EACrC,GAAG,EAAE,MAAM,KACR,MAAM,GAAG,SAAS,CAAC;AAExB;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,WAAW,CAyB5D;AAED,+DAA+D;AAC/D,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,cAAc,CAgEpE"}
@@ -0,0 +1,123 @@
1
+ import { posix } from 'node:path';
2
+ /** 에이전트가 처음 여는 문서. 폴더 안내판인 INDEX는 들어오는 링크가 없을 때만 진입점으로 본다 */
3
+ const ENTRY_NAMES = new Set([
4
+ 'readme.md',
5
+ 'claude.md',
6
+ 'agents.md',
7
+ 'skill.md',
8
+ 'knowledge_index.md',
9
+ ]);
10
+ const INDEX_NAME = 'index.md';
11
+ /** 상대 링크를 레포 기준 경로로 편다. 레포 밖이나 바깥 주소면 undefined */
12
+ export function resolveDocLink(fromPath, link) {
13
+ if (/^[a-z]+:/i.test(link) || link.startsWith('#'))
14
+ return undefined;
15
+ const clean = link.replace(/[#?].*$/, '');
16
+ if (clean === '')
17
+ return undefined;
18
+ const joined = clean.startsWith('/')
19
+ ? posix.normalize(clean.slice(1))
20
+ : posix.normalize(posix.join(posix.dirname(fromPath), clean));
21
+ return joined.startsWith('..') ? undefined : joined;
22
+ }
23
+ const keyOf = (d) => `${d.repoId}/${d.path}`;
24
+ /**
25
+ * 문서에 적힌 md 경로를 훑은 문서 하나로 푼다. 돌려주는 값은 `<repoId>/<path>`다.
26
+ * 문서 폴더 기준으로 먼저 본다. 안 맞으면 위 폴더로 한 단씩 올라가며 붙여 본다. 옆 스킬이나 레포 루트 기준으로 적은 경로가 여기서 풀린다.
27
+ * 그래도 없으면 같은 레포에서 뒷부분이 맞는 문서가 하나뿐일 때만 그 문서로 본다
28
+ */
29
+ export function docResolver(scan) {
30
+ const keys = new Set(scan.docs.map(keyOf));
31
+ const byName = new Map();
32
+ for (const k of keys) {
33
+ const base = posix.basename(k);
34
+ byName.set(base, [...(byName.get(base) ?? []), k]);
35
+ }
36
+ return (doc, ref) => {
37
+ const has = (p) => p !== undefined && keys.has(`${doc.repoId}/${p}`) ? `${doc.repoId}/${p}` : undefined;
38
+ const raw = ref.replace(/^\$\{?REPO_ROOT\}?\//, '/');
39
+ const direct = has(resolveDocLink(doc.path, raw));
40
+ if (direct !== undefined || /^[a-z]+:/i.test(raw))
41
+ return direct;
42
+ const rest = posix.normalize(raw.replace(/[#?].*$/, '').replace(/^(\.{0,2}\/)+/, ''));
43
+ if (rest.startsWith('..') || rest === '.')
44
+ return undefined;
45
+ for (let dir = posix.dirname(doc.path);; dir = posix.dirname(dir)) {
46
+ const hit = has(dir === '.' ? rest : `${dir}/${rest}`);
47
+ if (hit !== undefined)
48
+ return hit;
49
+ if (dir === '.')
50
+ break;
51
+ }
52
+ const hits = (byName.get(posix.basename(rest)) ?? []).filter((k) => k.startsWith(`${doc.repoId}/`) && k.endsWith(`/${rest}`));
53
+ return hits.length === 1 ? hits[0] : undefined;
54
+ };
55
+ }
56
+ /** 질문 안내 표와 문서 사이 링크로 질문 길을 따라가 고립 문서, 막다른 안내, 같은 말 충돌을 찾는다 */
57
+ export function analyzeDocRoutes(scan) {
58
+ const keys = new Set(scan.docs.map(keyOf));
59
+ const resolve = docResolver(scan);
60
+ const out = new Map();
61
+ const inbound = new Set();
62
+ const deadRoutes = [];
63
+ const keywordTargets = new Map();
64
+ const keywords = new Map();
65
+ for (const d of scan.docs) {
66
+ const from = keyOf(d);
67
+ const next = new Set();
68
+ const add = (k) => {
69
+ if (k === undefined || k === from)
70
+ return;
71
+ next.add(k);
72
+ inbound.add(k);
73
+ };
74
+ for (const l of d.mdLinks)
75
+ add(keys.has(`${d.repoId}/${l}`) ? `${d.repoId}/${l}` : undefined);
76
+ for (const r of d.mdRefs ?? [])
77
+ add(resolve(d, r));
78
+ for (const r of d.routes) {
79
+ const target = resolve(d, r.link ?? r.targetPath);
80
+ if (target === undefined) {
81
+ deadRoutes.push({ from, keywords: r.keywords, targetPath: r.targetPath });
82
+ continue;
83
+ }
84
+ add(target);
85
+ for (const raw of r.keywords) {
86
+ const kw = raw.toLowerCase();
87
+ keywordTargets.set(kw, (keywordTargets.get(kw) ?? new Set()).add(target));
88
+ keywords.set(target, (keywords.get(target) ?? new Set()).add(raw));
89
+ }
90
+ }
91
+ out.set(from, next);
92
+ }
93
+ const entries = scan.docs
94
+ .filter((d) => {
95
+ const name = posix.basename(d.path).toLowerCase();
96
+ return ENTRY_NAMES.has(name) || (name === INDEX_NAME && !inbound.has(keyOf(d)));
97
+ })
98
+ .map(keyOf)
99
+ .sort();
100
+ const seen = new Set(entries);
101
+ const queue = [...entries];
102
+ while (queue.length > 0) {
103
+ for (const n of out.get(queue.pop()) ?? []) {
104
+ if (seen.has(n))
105
+ continue;
106
+ seen.add(n);
107
+ queue.push(n);
108
+ }
109
+ }
110
+ const conflicts = [...keywordTargets]
111
+ .filter(([, t]) => t.size > 1)
112
+ .map(([keyword, t]) => ({ keyword, targets: [...t].sort() }))
113
+ .sort((a, b) => (a.keyword < b.keyword ? -1 : 1));
114
+ return {
115
+ entries,
116
+ reachable: seen.size,
117
+ orphans: entries.length === 0 ? [] : [...keys].filter((k) => !seen.has(k)).sort(),
118
+ deadRoutes,
119
+ conflicts,
120
+ keywords: Object.fromEntries([...keywords].map(([k, v]) => [k, [...v]])),
121
+ };
122
+ }
123
+ //# sourceMappingURL=doc-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doc-routes.js","sourceRoot":"","sources":["../../../src/architecture/doc-routes.ts"],"names":[],"mappings":"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"}