@tienne/gestalt 0.93.2 → 0.95.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 (74) hide show
  1. package/CLAUDE.md +15 -107
  2. package/README.ko.md +1 -0
  3. package/README.md +1 -0
  4. package/dist/package.json +1 -1
  5. package/dist/plugin/skills/_shared/agent-delegation.md +3 -1
  6. package/dist/plugin/skills/_shared/agent-model.md +62 -3
  7. package/dist/plugin/skills/_shared/proactive-routing.md +1 -0
  8. package/dist/plugin/skills/architecture/SKILL.md +15 -1
  9. package/dist/plugin/skills/architecture/references/domain-flow.md +1 -1
  10. package/dist/plugin/skills/architecture/references/rerun.md +1 -0
  11. package/dist/plugin/skills/blast-radius/SKILL.md +1 -0
  12. package/dist/plugin/skills/brief/SKILL.md +2 -0
  13. package/dist/plugin/skills/dispatch/SKILL.md +1 -1
  14. package/dist/plugin/skills/execute/SKILL.md +4 -1
  15. package/dist/plugin/skills/explain/SKILL.md +1 -0
  16. package/dist/plugin/skills/handoff/SKILL.md +188 -0
  17. package/dist/plugin/skills/jira-create/SKILL.md +1 -0
  18. package/dist/plugin/skills/pr/SKILL.md +2 -0
  19. package/dist/plugin/skills/presentation/SKILL.md +2 -0
  20. package/dist/plugin/skills/review/SKILL.md +7 -0
  21. package/dist/plugin/skills/review-reply/SKILL.md +1 -0
  22. package/dist/plugin/skills/slack-send/SKILL.md +1 -0
  23. package/dist/src/architecture/flow-layout.d.ts +12 -1
  24. package/dist/src/architecture/flow-layout.d.ts.map +1 -1
  25. package/dist/src/architecture/flow-layout.js +20 -4
  26. package/dist/src/architecture/flow-layout.js.map +1 -1
  27. package/dist/src/architecture/html-client.d.ts +2 -0
  28. package/dist/src/architecture/html-client.d.ts.map +1 -1
  29. package/dist/src/architecture/html-client.js +22 -4
  30. package/dist/src/architecture/html-client.js.map +1 -1
  31. package/dist/src/architecture/html-renderer.d.ts +1 -1
  32. package/dist/src/architecture/html-renderer.d.ts.map +1 -1
  33. package/dist/src/architecture/html-renderer.js +42 -8
  34. package/dist/src/architecture/html-renderer.js.map +1 -1
  35. package/dist/src/architecture/html-theme.d.ts +2 -0
  36. package/dist/src/architecture/html-theme.d.ts.map +1 -1
  37. package/dist/src/architecture/html-theme.js +7 -0
  38. package/dist/src/architecture/html-theme.js.map +1 -1
  39. package/dist/src/architecture/ir-schema.d.ts +63 -0
  40. package/dist/src/architecture/ir-schema.d.ts.map +1 -1
  41. package/dist/src/architecture/ir-schema.js +16 -0
  42. package/dist/src/architecture/ir-schema.js.map +1 -1
  43. package/dist/src/architecture/types.d.ts +15 -0
  44. package/dist/src/architecture/types.d.ts.map +1 -1
  45. package/dist/src/architecture/types.js.map +1 -1
  46. package/dist/src/architecture/validator.js +1 -1
  47. package/dist/src/architecture/validator.js.map +1 -1
  48. package/dist/src/mcp/server.js +2 -2
  49. package/dist/src/mcp/server.js.map +1 -1
  50. package/dist/src/mcp/tools/agent-passthrough.d.ts.map +1 -1
  51. package/dist/src/mcp/tools/agent-passthrough.js +28 -28
  52. package/dist/src/mcp/tools/agent-passthrough.js.map +1 -1
  53. package/package.json +1 -1
  54. package/plugin/.codex-plugin/plugin.json +1 -1
  55. package/plugin/.mcp.json +1 -1
  56. package/plugin/mcp.json +1 -1
  57. package/plugin/skills/_shared/agent-delegation.md +3 -1
  58. package/plugin/skills/_shared/agent-model.md +62 -3
  59. package/plugin/skills/_shared/proactive-routing.md +1 -0
  60. package/plugin/skills/architecture/SKILL.md +15 -1
  61. package/plugin/skills/architecture/references/domain-flow.md +1 -1
  62. package/plugin/skills/architecture/references/rerun.md +1 -0
  63. package/plugin/skills/blast-radius/SKILL.md +1 -0
  64. package/plugin/skills/brief/SKILL.md +2 -0
  65. package/plugin/skills/dispatch/SKILL.md +1 -1
  66. package/plugin/skills/execute/SKILL.md +4 -1
  67. package/plugin/skills/explain/SKILL.md +1 -0
  68. package/plugin/skills/handoff/SKILL.md +188 -0
  69. package/plugin/skills/jira-create/SKILL.md +1 -0
  70. package/plugin/skills/pr/SKILL.md +2 -0
  71. package/plugin/skills/presentation/SKILL.md +2 -0
  72. package/plugin/skills/review/SKILL.md +7 -0
  73. package/plugin/skills/review-reply/SKILL.md +1 -0
  74. package/plugin/skills/slack-send/SKILL.md +1 -0
@@ -2,6 +2,24 @@ import { BAND_LINE_X, BAND_LINE_Y, BAND_TITLE_HALF, BAND_TITLE_X } from './canva
2
2
  import { FOCUS_SOURCE } from './focus.js';
3
3
  import { PRODUCT_COLORS } from './html-theme.js';
4
4
  import { FRAME_PAD, NODE_DESC_LINE } from './layout.js';
5
+ // 화면 캡처 조각은 캡처가 있는 그림에만 싣는다. 늘 실으면 캡처가 없는 그림의 바이트까지 바뀐다
6
+ const CAPTURE_CODE = ` var CAPTURE_SOURCE = { browser: '실행 화면', figma: '피그마 프레임' };
7
+ function renderCapture(n, body, withCaption) {
8
+ var cp = n.capture;
9
+ if (!cp) return;
10
+ var fig = el('figure', 'capture');
11
+ var img = el('img');
12
+ img.src = cp.image;
13
+ img.alt = nameOf(n) + ' 화면 캡처';
14
+ fig.appendChild(img);
15
+ var note = (withCaption ? nameOf(n) + ': ' : '') + (CAPTURE_SOURCE[cp.source] || cp.source) + ', ' + cp.env + ', ' + cp.capturedAt;
16
+ fig.appendChild(el('figcaption', 'desc', note));
17
+ body.appendChild(fig);
18
+ }
19
+ `;
20
+ const THUMB_CLICK = " var thumb = e.target.closest('.flow-thumb');\n" +
21
+ " if (thumb) { activateNode(thumb.getAttribute('data-step-id'), e, false); return; }\n";
22
+ const CAPTURE_STEP_CALL = ' refs.forEach(function (r) { renderCapture(nodes[r], body, true); });\n';
5
23
  // component는 칩 글자를 노드의 displayKind에서, 색과 아이콘은 renderClass에서 가져온다. types.ts의 displayKindOf, chipTextOverride와 같은 규칙이다.
6
24
  // 이 조각은 component를 쓸 수 있는 어휘에만 싣는다. 늘 실으면 component가 없는 그림의 바이트까지 바뀐다
7
25
  const COMPONENT_DKIND = "n.kind === 'component' ? 'cx_' + (n.renderClass || 'service') : ";
@@ -700,7 +718,7 @@ ${FOCUS_SOURCE}
700
718
  if (st.description) body.appendChild(el('p', 'desc', st.description));
701
719
  questionList(body, st.questions);
702
720
  ${c.flowBranches ? BRANCH_STEP_OUTS : ''} var refs = (st.refs || []).filter(function (r) { return !!nodes[r]; });
703
- if (refs.length) {
721
+ ${c.captures ? CAPTURE_STEP_CALL : ''} if (refs.length) {
704
722
  var web = refs.every(function (r) { return nodes[r].kind === 'screen' || nodes[r].kind === 'endpoint'; });
705
723
  body.appendChild(el('h3', null, (web ? '이어진 화면과 API ' : '이어진 카드 ') + refs.length + '개'));
706
724
  refButtons(body, refs, function (r) { goToRef(r, f.service); }, function (r) { return 'i-' + dkind(nodes[r]); }, label);
@@ -812,7 +830,7 @@ ${c.flowBranches ? BRANCH_TRANSITION_FACTS : ''} var f = stepFlow[t.from];
812
830
  panel.appendChild(body);
813
831
  openDrawer();
814
832
  }
815
- function renderPanel(id) {
833
+ ${c.captures ? CAPTURE_CODE : ''} function renderPanel(id) {
816
834
  if (isStep(id)) { renderStepPanel(id); return; }
817
835
  var n = nodes[id];
818
836
  panel.textContent = '';
@@ -864,7 +882,7 @@ ${c.flowBranches ? BRANCH_TRANSITION_FACTS : ''} var f = stepFlow[t.from];
864
882
  body.appendChild(el('h3', null, '이 종류는'));
865
883
  body.appendChild(el('p', 'desc', about));
866
884
  }
867
- renderFacts(n, body);${c.docs ? '\n renderDoc(n, body);' : ''}
885
+ renderFacts(n, body);${c.captures ? '\n renderCapture(n, body, false);' : ''}${c.docs ? '\n renderDoc(n, body);' : ''}
868
886
  if (flowsBySvc[id]) {
869
887
  body.appendChild(el('h3', null, '흐름 ' + flowsBySvc[id].length + '개'));
870
888
  refButtons(body, flowsBySvc[id].map(function (f) { return f.level; }), showLevel, function () { return 'u-flow'; }, function (lv) { return levels[lv].title; });
@@ -1162,7 +1180,7 @@ ${c.views ? viewFuncs(!!c.sequences) : ''}${c.sequences ? SEQ_FUNCS : ''}${c.doc
1162
1180
  }
1163
1181
  ${c.views ? VIEW_CLICK : ''}var card = e.target.closest('.node');
1164
1182
  if (card) { activateNode(card.getAttribute('data-node-id'), e, false); return; }
1165
- var link = e.target.closest('.link.bundle');
1183
+ ${c.captures ? THUMB_CLICK : ''} var link = e.target.closest('.link.bundle');
1166
1184
  if (link) { activateBundle(link); return; }
1167
1185
  var ft = e.target.closest('.link.flow-t');
1168
1186
  if (ft) { activateTransition(ft); return; }
@@ -1 +1 @@
1
- {"version":3,"file":"html-client.js","sourceRoot":"","sources":["../../../src/architecture/html-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"html-client.js","sourceRoot":"","sources":["../../../src/architecture/html-client.ts"],"names":[],"mappings":"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"}
@@ -18,5 +18,5 @@ export declare function renderArchitectureHtml(validated: ValidatedIr, layout: L
18
18
  * 드릴다운 HTML. 레벨마다 미리 그린 캔버스를 한 파일에 넣고 하나만 보이게 한다.
19
19
  * 같은 입력이면 같은 바이트가 나온다. shared면 private 근거를 가린 사본으로 그린다.
20
20
  */
21
- export declare function renderDrilldownHtml(validated: ValidatedIr, drilldown: Drilldown, opts: RenderArchitectureHtmlOptions): string;
21
+ export declare function renderDrilldownHtml(validated: ValidatedIr, drilldownIn: Drilldown, opts: RenderArchitectureHtmlOptions): string;
22
22
  //# sourceMappingURL=html-renderer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"html-renderer.d.ts","sourceRoot":"","sources":["../../../src/architecture/html-renderer.ts"],"names":[],"mappings":"AAWA,OAAO,EAAqD,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AA8BnG,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AAiCrB,OAAO,EAAoC,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAEpF,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,QAAQ,CAAC;AAExD,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,EAAE,oBAAoB,CAAC;CAChC;AAkFD,mEAAmE;AACnE,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAetD;AA2VD,6DAA6D;AAC7D,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAEjE;AA+9CD;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,WAAW,EACtB,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,6BAA6B,GAClC,MAAM,CAkBR;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,WAAW,EACtB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,6BAA6B,GAClC,MAAM,CAsJR"}
1
+ {"version":3,"file":"html-renderer.d.ts","sourceRoot":"","sources":["../../../src/architecture/html-renderer.ts"],"names":[],"mappings":"AAWA,OAAO,EAAqD,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AA+BnG,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AAiCrB,OAAO,EAAoC,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAEpF,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,QAAQ,CAAC;AAExD,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,EAAE,oBAAoB,CAAC;CAChC;AAkFD,mEAAmE;AACnE,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAetD;AA2VD,6DAA6D;AAC7D,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAEjE;AAm/CD;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,WAAW,EACtB,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,6BAA6B,GAClC,MAAM,CAkBR;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,WAAW,EACtB,WAAW,EAAE,SAAS,EACtB,IAAI,EAAE,6BAA6B,GAClC,MAAM,CA+KR"}
@@ -1,7 +1,8 @@
1
1
  import { BAND_LINE_X, BAND_LINE_Y, BAND_TITLE_HALF, BAND_TITLE_X, CANVAS_PAD_TOP, CANVAS_PAD_X, LANE_INSET_Y, routeCanvas, } from './canvas-geometry.js';
2
2
  import { flowCountByService, ROOT_LEVEL_ID } from './drilldown.js';
3
+ import { computeFlowLayout } from './flow-layout.js';
3
4
  import { renderClientScript, THEME_BOOT_SCRIPT } from './html-client.js';
4
- import { datastoreEngine, iconUse, PRODUCT_COLORS, renderCss, renderIconSprite, VIEW_CSS, DOC_CSS, FLOW_BRANCH_CSS, SEQ_VIEW_CSS, } from './html-theme.js';
5
+ import { datastoreEngine, iconUse, PRODUCT_COLORS, renderCss, renderIconSprite, VIEW_CSS, CAPTURE_CSS, DOC_CSS, FLOW_BRANCH_CSS, SEQ_VIEW_CSS, } from './html-theme.js';
5
6
  import { EDGE_KIND_ABOUT, LANE_ABOUT, LANE_TITLES, NODE_KIND_ABOUT, STAGE_LANE_ABOUT, flowBadgeText, MICRO_HOST_SHORT, NODE_KIND_SHORT, PLATFORM_CHIP_TEXT, PLATFORM_NAME, WEB_HOSTING_CHIP_TEXT, WEB_HOSTING_NAME, platformChipText, platformName, } from './kind-text.js';
6
7
  import { compareEnvironment, FLAT_BACKWARD_EDGE_KINDS, textUnits, } from './layout.js';
7
8
  import { indexMicroApps } from './micro-app.js';
@@ -550,7 +551,7 @@ function roundedPathD(points) {
550
551
  * 흐름 레벨 하나. 행위자마다 가로줄을 깔고 단계 카드를 왼쪽에서 오른쪽으로 놓는다.
551
552
  * 카드는 노드 카드와 같은 .node라 강조와 검색, 질문 이동을 그대로 탄다. data-node-id 자리에 단계 id가 들어간다
552
553
  */
553
- function renderFlowSection(level, flow, questionCount, drawableNodes) {
554
+ function renderFlowSection(level, flow, questionCount, drawableNodes, captureOf) {
554
555
  const { layout } = level;
555
556
  const width = round2(layout.width + FLOW_PAD * 2);
556
557
  const height = round2(layout.height + FLOW_PAD * 2);
@@ -628,6 +629,21 @@ function renderFlowSection(level, flow, questionCount, drawableNodes) {
628
629
  `<path class="edge" d="${d}" stroke-width="2"${dash}/><polygon class="tip" points="${tip}"/>${text}</g>`);
629
630
  })
630
631
  .join('');
632
+ // 선 레이어보다 먼저 놓아 전이 선이 썸네일 위로 지나가게 한다. 선이 가려지면 있는 연결이 없는 것처럼 읽힌다
633
+ const thumbs = layout.steps
634
+ .map((b) => {
635
+ if (b.thumb === undefined)
636
+ return '';
637
+ const cap = (stepById.get(b.id).refs ?? [])
638
+ .map((r) => captureOf.get(r))
639
+ .find((c) => c !== undefined);
640
+ if (cap === undefined)
641
+ return '';
642
+ return (`<div class="flow-thumb" data-step-id="${escapeHtml(b.id)}" ` +
643
+ `style="left:${round2(b.x + FLOW_PAD)}px;top:${round2(b.thumb.y + FLOW_PAD)}px;width:${b.width}px;height:${b.thumb.height}px">` +
644
+ `<img src="${escapeHtml(cap.image)}" alt="${escapeHtml(`${cap.label} 화면 캡처`)}" loading="lazy" draggable="false"></div>`);
645
+ })
646
+ .join('');
631
647
  const cards = layout.steps
632
648
  .map((b) => {
633
649
  const st = stepById.get(b.id);
@@ -669,6 +685,7 @@ function renderFlowSection(level, flow, questionCount, drawableNodes) {
669
685
  .join('');
670
686
  return (`<section class="level flow-level" data-level-id="${escapeHtml(level.id)}" data-flow-id="${escapeHtml(level.flowId)}" ` +
671
687
  `aria-label="${escapeHtml(solo !== undefined ? `${flow.title}, 행위자 ${solo.actor.label}` : flow.title)}" data-w="${width}" data-h="${height}" style="width:${width}px;height:${height}px" hidden>` +
688
+ thumbs +
672
689
  `<svg class="links" xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" ` +
673
690
  `role="group" aria-label="${escapeHtml(`${flow.title} 전이`)}"><g class="lanes">${lanes}${dividers}</g><g class="edges">${links}</g></svg>` +
674
691
  `${stageHeads}${heads}${cards}</section>`);
@@ -1292,8 +1309,8 @@ function renderBar(title, drill, generatedAt, nodeCount, edgeCount, questionCoun
1292
1309
  }
1293
1310
  const clientScripts = new Map();
1294
1311
  /** 칩 글자와 설명, 레인 제목은 IR이 쓰는 팩 것만 싣는다. 팩을 더해도 그 팩을 안 쓰는 그림의 바이트가 그대로다 */
1295
- function clientScriptFor(vocab, rootFlows, views, mixedBundles, sequences, flowBranches) {
1296
- const key = `${vocab.packIds.join(',')}|${rootFlows}|${views}|${mixedBundles}|${sequences}|${flowBranches}`;
1312
+ function clientScriptFor(vocab, rootFlows, views, mixedBundles, sequences, flowBranches, captures) {
1313
+ const key = `${vocab.packIds.join(',')}|${rootFlows}|${views}|${mixedBundles}|${sequences}|${flowBranches}|${captures}`;
1297
1314
  const hit = clientScripts.get(key);
1298
1315
  if (hit !== undefined)
1299
1316
  return hit;
@@ -1327,6 +1344,7 @@ function clientScriptFor(vocab, rootFlows, views, mixedBundles, sequences, flowB
1327
1344
  mixedBundles,
1328
1345
  sequences,
1329
1346
  ...(flowBranches ? { flowBranches } : {}),
1347
+ ...(captures ? { captures } : {}),
1330
1348
  docs: vocab.packIds.includes('knowledge'),
1331
1349
  });
1332
1350
  clientScripts.set(key, script);
@@ -1355,6 +1373,7 @@ function renderPage({ ir, payload, sections, drill, flows, views, mixedBundles =
1355
1373
  flows.drawnSteps.has(t.from) &&
1356
1374
  flows.drawnSteps.has(t.to)));
1357
1375
  const soloActor = drawnFlows.some((f) => f.actors.length === 1);
1376
+ const hasCaptures = ir.nodes.some((n) => n.capture !== undefined);
1358
1377
  return [
1359
1378
  '<!doctype html>',
1360
1379
  '<html lang="ko">',
@@ -1363,7 +1382,7 @@ function renderPage({ ir, payload, sections, drill, flows, views, mixedBundles =
1363
1382
  '<meta name="viewport" content="width=device-width, initial-scale=1">',
1364
1383
  `<title>${escapeHtml(title)}</title>`,
1365
1384
  `<script>${THEME_BOOT_SCRIPT}</script>`,
1366
- `<style>${renderCss(vocab)}${hasViews ? `\n${VIEW_CSS}` : ''}${hasSequences ? `\n${SEQ_VIEW_CSS}` : ''}${vocab.packIds.includes('knowledge') ? `\n${DOC_CSS}` : ''}${flowBranches || soloActor ? `\n${FLOW_BRANCH_CSS}` : ''}</style>`,
1385
+ `<style>${renderCss(vocab)}${hasViews ? `\n${VIEW_CSS}` : ''}${hasSequences ? `\n${SEQ_VIEW_CSS}` : ''}${vocab.packIds.includes('knowledge') ? `\n${DOC_CSS}` : ''}${hasCaptures ? `\n${CAPTURE_CSS}` : ''}${flowBranches || soloActor ? `\n${FLOW_BRANCH_CSS}` : ''}</style>`,
1367
1386
  '</head>',
1368
1387
  '<body>',
1369
1388
  renderIconSprite(vocab),
@@ -1390,7 +1409,7 @@ function renderPage({ ir, payload, sections, drill, flows, views, mixedBundles =
1390
1409
  ? '<div id="flow-pop" class="pop" role="dialog" aria-label="흐름 고르기" tabindex="-1" hidden><h3>흐름</h3><ul class="flow-list"></ul></div>'
1391
1410
  : '') + (hasViews ? `\n${renderViewsPop(views)}` : ''),
1392
1411
  `<script id="ir" type="application/json">${embedJson(stableStringify(payload))}</script>`,
1393
- `<script>${clientScriptFor(vocab, hasFlows && flows.flows.some((f) => f.service === undefined), hasViews, mixedBundles, hasSequences, flowBranches)}</script>`,
1412
+ `<script>${clientScriptFor(vocab, hasFlows && flows.flows.some((f) => f.service === undefined), hasViews, mixedBundles, hasSequences, flowBranches, hasCaptures)}</script>`,
1394
1413
  '</body>',
1395
1414
  '</html>',
1396
1415
  '',
@@ -1423,9 +1442,24 @@ export function renderArchitectureHtml(validated, layout, opts) {
1423
1442
  * 드릴다운 HTML. 레벨마다 미리 그린 캔버스를 한 파일에 넣고 하나만 보이게 한다.
1424
1443
  * 같은 입력이면 같은 바이트가 나온다. shared면 private 근거를 가린 사본으로 그린다.
1425
1444
  */
1426
- export function renderDrilldownHtml(validated, drilldown, opts) {
1445
+ export function renderDrilldownHtml(validated, drilldownIn, opts) {
1427
1446
  const shared = opts.audience === 'shared';
1428
1447
  const ir = shared ? redactForSharing(validated.ir) : validated.ir;
1448
+ // 공유본은 캡처를 싣지 않으니 썸네일 자리도 비운다. 자리만 남기면 빈 칸이 어디 있는지 드러난다
1449
+ const drilldown = shared
1450
+ ? {
1451
+ ...drilldownIn,
1452
+ flows: drilldownIn.flows.map((l) => l.layout.steps.some((b) => b.thumb !== undefined)
1453
+ ? {
1454
+ ...l,
1455
+ layout: computeFlowLayout(l.flow, validated.drawableStepIds, validated.drawableTransitionIds),
1456
+ }
1457
+ : l),
1458
+ }
1459
+ : drilldownIn;
1460
+ const captureOf = new Map(ir.nodes.flatMap((n) => n.capture !== undefined
1461
+ ? [[n.id, { image: n.capture.image, label: nodeName(n) }]]
1462
+ : []));
1429
1463
  const base = buildPayload(ir, validated, shared);
1430
1464
  const docCover = docCoverSpec(base.nodes, base.docOverlay);
1431
1465
  const nodeById = new Map(base.nodes.map((n) => [n.id, n]));
@@ -1524,7 +1558,7 @@ export function renderDrilldownHtml(validated, drilldown, opts) {
1524
1558
  }
1525
1559
  : {}),
1526
1560
  }))
1527
- .concat(flowLevels.map(({ level, flow }) => renderFlowSection(level, flow, questionCount, drawableNodes)))
1561
+ .concat(flowLevels.map(({ level, flow }) => renderFlowSection(level, flow, questionCount, drawableNodes, captureOf)))
1528
1562
  .concat(views.map((v) => {
1529
1563
  const p = v.projection;
1530
1564
  if (p.shape === 'dataflow') {