@tienne/gestalt 0.96.0 → 0.97.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.
- package/dist/package.json +1 -1
- package/dist/plugin/skills/architecture/SKILL.md +31 -5
- package/dist/plugin/skills/architecture/references/domain-flow.md +1 -0
- package/dist/plugin/skills/architecture/references/projections.md +56 -0
- package/dist/plugin/skills/architecture/references/rerun.md +3 -1
- package/dist/schemas/architecture-ir.schema.json +51 -3
- package/dist/src/architecture/blueprint-layout.d.ts +105 -0
- package/dist/src/architecture/blueprint-layout.d.ts.map +1 -0
- package/dist/src/architecture/blueprint-layout.js +297 -0
- package/dist/src/architecture/blueprint-layout.js.map +1 -0
- package/dist/src/architecture/delta-renderer.d.ts +35 -0
- package/dist/src/architecture/delta-renderer.d.ts.map +1 -0
- package/dist/src/architecture/delta-renderer.js +329 -0
- package/dist/src/architecture/delta-renderer.js.map +1 -0
- package/dist/src/architecture/delta.d.ts +70 -0
- package/dist/src/architecture/delta.d.ts.map +1 -0
- package/dist/src/architecture/delta.js +342 -0
- package/dist/src/architecture/delta.js.map +1 -0
- package/dist/src/architecture/drilldown.d.ts +19 -1
- package/dist/src/architecture/drilldown.d.ts.map +1 -1
- package/dist/src/architecture/drilldown.js +5 -5
- package/dist/src/architecture/drilldown.js.map +1 -1
- package/dist/src/architecture/er-layout.d.ts +97 -0
- package/dist/src/architecture/er-layout.d.ts.map +1 -0
- package/dist/src/architecture/er-layout.js +344 -0
- package/dist/src/architecture/er-layout.js.map +1 -0
- package/dist/src/architecture/flow-layout.d.ts +22 -1
- package/dist/src/architecture/flow-layout.d.ts.map +1 -1
- package/dist/src/architecture/flow-layout.js +13 -9
- package/dist/src/architecture/flow-layout.js.map +1 -1
- package/dist/src/architecture/html-renderer.d.ts +4 -0
- package/dist/src/architecture/html-renderer.d.ts.map +1 -1
- package/dist/src/architecture/html-renderer.js +462 -20
- package/dist/src/architecture/html-renderer.js.map +1 -1
- package/dist/src/architecture/html-theme.d.ts +18 -0
- package/dist/src/architecture/html-theme.d.ts.map +1 -1
- package/dist/src/architecture/html-theme.js +101 -1
- package/dist/src/architecture/html-theme.js.map +1 -1
- package/dist/src/architecture/ir-schema.d.ts +358 -117
- package/dist/src/architecture/ir-schema.d.ts.map +1 -1
- package/dist/src/architecture/ir-schema.js +33 -1
- package/dist/src/architecture/ir-schema.js.map +1 -1
- package/dist/src/architecture/lifecycle-layout.d.ts +94 -0
- package/dist/src/architecture/lifecycle-layout.d.ts.map +1 -0
- package/dist/src/architecture/lifecycle-layout.js +471 -0
- package/dist/src/architecture/lifecycle-layout.js.map +1 -0
- package/dist/src/architecture/merge.d.ts.map +1 -1
- package/dist/src/architecture/merge.js +72 -2
- package/dist/src/architecture/merge.js.map +1 -1
- package/dist/src/architecture/store.d.ts +6 -1
- package/dist/src/architecture/store.d.ts.map +1 -1
- package/dist/src/architecture/store.js +75 -8
- package/dist/src/architecture/store.js.map +1 -1
- package/dist/src/architecture/types.d.ts +35 -3
- package/dist/src/architecture/types.d.ts.map +1 -1
- package/dist/src/architecture/types.js +13 -1
- package/dist/src/architecture/types.js.map +1 -1
- package/dist/src/architecture/validator.d.ts +27 -3
- package/dist/src/architecture/validator.d.ts.map +1 -1
- package/dist/src/architecture/validator.js +331 -8
- package/dist/src/architecture/validator.js.map +1 -1
- package/dist/src/mcp/tools/architecture-passthrough.d.ts.map +1 -1
- package/dist/src/mcp/tools/architecture-passthrough.js +91 -2
- package/dist/src/mcp/tools/architecture-passthrough.js.map +1 -1
- package/package.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/.mcp.json +1 -1
- package/plugin/mcp.json +1 -1
- package/plugin/skills/architecture/SKILL.md +31 -5
- package/plugin/skills/architecture/references/domain-flow.md +1 -0
- package/plugin/skills/architecture/references/projections.md +56 -0
- package/plugin/skills/architecture/references/rerun.md +3 -1
- package/schemas/architecture-ir.schema.json +51 -3
package/dist/package.json
CHANGED
|
@@ -114,6 +114,9 @@ Step 0 전에 두 가지를 정한다. 대상에 맞는 어휘 팩과 질문에
|
|
|
114
114
|
| 데이터가 어디서 와서 어디로 가나 | `dataflow` 질문별 그림 |
|
|
115
115
|
| 둘이 무엇이 같고 무엇이 다른가 | `compare` 질문별 그림 |
|
|
116
116
|
| 상태나 단계, 업무 절차 | `flows` ([Step 3.5](#step-35--도메인-흐름)) |
|
|
117
|
+
| 한 대상이 어떤 상태를 거쳐 어디서 끝나나 | `flows`를 먼저 쓰고 그 위에 `lifecycle` 질문별 그림 |
|
|
118
|
+
| 고객이 한 걸음 갈 때 뒤에서 무엇이 일하나 | `flows`를 먼저 쓰고 그 위에 `blueprint` 질문별 그림 |
|
|
119
|
+
| 테이블끼리 어떤 컬럼으로 묶이나 | `db_table`에 `columns`를 먼저 쓰고 그 위에 `er` 질문별 그림 |
|
|
117
120
|
| 분명하지 않다 | 지도를 그리고 Step 8 보고에서 포커스 쓰는 법을 안내한다 |
|
|
118
121
|
|
|
119
122
|
- 질문별 그림은 지도 위에 얹는다. 지도를 먼저 그린다. 답에 필요한 사실이 지도에 없으면 먼저 탐색해 근거와 함께 `nodes`와 `edges`에 넣는다. 그다음에 질문별 그림에서 가리킨다. 끝내 못 찾은 사실은 그리지 않고 미해결 질문으로 남긴다.
|
|
@@ -262,6 +265,7 @@ Step 0 전에 두 가지를 정한다. 대상에 맞는 어휘 팩과 질문에
|
|
|
262
265
|
- `repo`는 클라우드 조회용 가짜 레포 id로 두고 label은 `<엔진>:<클러스터 식별자>` 꼴(`aurora-mysql:<식별자>`, `redis:<식별자>`)로 쓴다. 다른 분석과 합칠 때 같은 클러스터가 한 노드로 모이는 기준이 이 label이다.
|
|
263
266
|
- `engine`에 엔진 이름(`mysql`, `postgresql`, `redis`, `elasticsearch`, `mongodb`, `documentdb`, `dynamodb`, `mariadb`)을 단다. 카드에 그 엔진 로고가 선다. Aurora MySQL은 `mysql`, ElastiCache Redis는 `redis`다. 안 달면 label 앞부분으로 찾지만 label을 다르게 적으면 로고가 안 붙는다.
|
|
264
267
|
- **id에는 클러스터 식별자와 계정 ID를 넣지 않는다.** `ds:redis-common`처럼 별칭으로 짓는다.
|
|
268
|
+
- 테이블 구조를 묻는 질문이 있을 때만 `db_table`에 `columns`를 단다. 출처는 마이그레이션 파일(`CREATE TABLE`, `ALTER TABLE ... ADD CONSTRAINT`), ORM 엔티티(JPA `@Entity`, TypeORM, Prisma `schema.prisma`, Django 모델), 스키마 덤프 파일이다. 컬럼 하나는 `{ name, type?, pk?, nullable?, unique?, references?, evidence? }`이고 외래 키는 `references: { table, column?, onDelete? }`에 대상 `db_table` id로 적는다. 외래 키 컬럼에는 그 제약을 적은 줄을 `evidence`로 단다. 근거가 없으면 선이 안 그려지고 `auto:fk:` 질문이 생긴다. 쓰임새는 [`references/projections.md`](./references/projections.md)의 er 항목에 있다.
|
|
265
269
|
- `environment`를 단다. 전체 그림은 prod 기준이라 `prod`가 아닌 저장소는 전체 그림에서 빠지고 아래 레벨에서만 보인다. 조회로 채울 때도 prod부터 채운다.
|
|
266
270
|
|
|
267
271
|
### 3-3. `gateway`
|
|
@@ -311,6 +315,10 @@ AI 클라이언트가 플러그인으로 읽어 들이는 스킬과 에이전트
|
|
|
311
315
|
> **이 단계의 상세** → [`references/domain-flow.md`](./references/domain-flow.md)
|
|
312
316
|
> screen-chain에서 상태나 단계, 업무 절차를 그릴 때만 이 파일을 읽고 따릅니다. 아니면 열지 않고 다음으로 갑니다.
|
|
313
317
|
|
|
318
|
+
흐름 그림은 행위자 줄 위에 단계를 늘어놓아 "누가 무엇을 하나"를 보여준다. "이 주문은 어떤 상태를 거쳐 어디서 끝나나"를 물으면 같은 흐름 위에 `lifecycle` 질문별 그림을 하나 더 얹는다. 단계의 `state`만 모아 진행 단계, 대기와 복구, 끝 상태 세 띠로 다시 그린 그림이라 따로 적을 사실이 없다. 끝 단계에 `outcome`(`done`, `cancel`, `fail`)을 달면 끝 상태 카드에 완료, 취소, 실패 배지가 붙는다. 상세는 [`references/projections.md`](./references/projections.md)의 lifecycle 항목에 있다.
|
|
319
|
+
|
|
320
|
+
"손님이 줄을 서는 동안 뒤에서는 어떤 API와 테이블이 일하나"처럼 고객 단계마다 화면 뒤를 물으면 `blueprint`를 얹는다. 정상 흐름 단계를 열로 세우고 위에서 아래로 고객 행동, 프론트스테이지, 가시선, 백스테이지, 지원 층에 나눠 담는다. 칸은 단계의 행위자와 `refs`, 거기서 이어지는 근거 있는 지도 엣지로만 채운다. 그래서 단계에 `refs`를 달아 둬야 칸이 찬다. 데이터가 어디로 흘러가는지가 궁금하면 `dataflow`, 호출 순서가 궁금하면 `sequence`이고 blueprint가 아니다. 상세는 [`references/projections.md`](./references/projections.md)의 blueprint 항목에 있다.
|
|
321
|
+
|
|
314
322
|
## Step 4 — 뷰② deploy-path 탐색
|
|
315
323
|
|
|
316
324
|
1. **배포 단위**: 레포마다 배포되는 단위를 정한다. 모노레포면 앱 하나가 단위다.
|
|
@@ -456,6 +464,9 @@ FE가 부르는 BE 레포나 배포 매니페스트 레포처럼 지금 레포
|
|
|
456
464
|
- 출처가 이미 있는 노드는 거기서 가져와 한 줄로 줄인다. 스킬은 SKILL.md 프런트매터의 `description`, MCP 도구는 도구 등록의 description, 에이전트는 AGENT.md의 `description`이나 첫 문단이다. 트리거 문구나 사용 예시는 걷어내고 하는 일만 남긴다.
|
|
457
465
|
- 출처가 없으면 코드에서 읽은 대로 쓴다. 화면은 사용자가 거기서 하는 일, API는 무엇을 돌려주거나 바꾸는지, 테이블은 무엇을 담는지다.
|
|
458
466
|
- 빈 채로 두면 validate가 `warnings`에 `NODE_DESCRIPTION_MISSING`을 싣는다. 에러가 아니라 render는 막지 않는다. 경고에 실린 `nodeIds`를 채워 다시 validate한다.
|
|
467
|
+
- 상태 흐름 그림이 한 장에 읽히는 양을 넘으면 `warnings`에 `LIFECYCLE_OVER_BUDGET`이 실린다. 이것도 render를 막지 않는다. 경고의 `counts`를 보고 세부 상태를 하나로 합치거나 흐름을 둘로 나눈다.
|
|
468
|
+
- 서비스 블루프린트의 단계 열이 6을 넘으면 `warnings`에 `BLUEPRINT_OVER_BUDGET`이 실린다. render는 막지 않는다. 같은 화면에서 이어지는 단계를 합치거나 흐름을 나눈다.
|
|
469
|
+
- 테이블 관계 그림이 테이블 5개, 한 테이블의 컬럼 8개, 외래 키 선 6개 중 하나라도 넘으면 `warnings`에 `ER_OVER_BUDGET`이 실린다. render는 막지 않는다. 질문에 걸린 테이블만 남기거나 그림을 나눈다.
|
|
459
470
|
|
|
460
471
|
### 페이지 글
|
|
461
472
|
|
|
@@ -537,10 +548,10 @@ FE가 부르는 BE 레포나 배포 매니페스트 레포처럼 지금 레포
|
|
|
537
548
|
|
|
538
549
|
### 질문별 그림을 얹는다
|
|
539
550
|
|
|
540
|
-
[모양 고르기](#모양-고르기)에서 `sequence`, `dataflow`, `compare
|
|
551
|
+
[모양 고르기](#모양-고르기)에서 `sequence`, `dataflow`, `compare`, `lifecycle`, `blueprint`, `er`을 골랐으면 지도를 다 쓴 뒤 `projections`에 그림을 단다. 질문별 그림은 지도의 노드와 엣지를 id로 가리킬 뿐이다. 새 사실을 여기에 먼저 적지 않는다. `lifecycle`과 `blueprint`는 노드 대신 `flows`의 흐름 하나를 `flow`로 가리킨다. `er`은 `participants`에 `db_table` id를 적고 선은 컬럼의 `references`에서 나온다.
|
|
541
552
|
|
|
542
553
|
> **이 단계의 상세** → [`references/projections.md`](./references/projections.md)
|
|
543
|
-
> `sequence`, `dataflow`, `compare
|
|
554
|
+
> `sequence`, `dataflow`, `compare`, `lifecycle`, `blueprint`, `er`을 골랐을 때만 이 파일을 읽고 따릅니다. 아니면 열지 않고 다음으로 갑니다.
|
|
544
555
|
|
|
545
556
|
### parent로 포함 관계를 단다
|
|
546
557
|
|
|
@@ -575,7 +586,10 @@ FE가 부르는 BE 레포나 배포 매니페스트 레포처럼 지금 레포
|
|
|
575
586
|
```
|
|
576
587
|
|
|
577
588
|
- 성공하면 `{ ok: true, autoUnresolved, drawable }`이다. `drawable`에 빠진 노드와 엣지가 있으면 왜 빠졌는지 `autoUnresolved`에서 확인한다.
|
|
578
|
-
- 성공해도 `warnings`가 올 수 있다.
|
|
589
|
+
- 성공해도 `warnings`가 올 수 있다. 어느 경고도 render를 막지 않는다. 고치는 법은 [노드 설명](#노드-설명)에 모아 두었다.
|
|
590
|
+
- `NODE_DESCRIPTION_MISSING`은 그리는 노드 중 `description`이 빈 노드를 `nodeIds`에 모아 준다. 그 카드에는 설명 줄이 없으니 채운다.
|
|
591
|
+
- 예산 경고(`LIFECYCLE_OVER_BUDGET`, `BLUEPRINT_OVER_BUDGET`, `ER_OVER_BUDGET`)에는 `nodeIds`가 없다. 넘친 그림의 id를 `subjectId`에, 넘친 개수를 `counts`에 담는다. 그림을 나누거나 줄이라는 신호다.
|
|
592
|
+
- render 응답에도 같은 `warnings`가 실린다. render에는 `DELTA_OVER_BUDGET`이 더 올 수 있다. 읽는 법은 [Step 8](#step-8--render와-보고)에 있다.
|
|
579
593
|
- 실패하면 `errors[]`에 `code`와 `nodeId`나 `edgeId`가 온다. 질문별 그림 에러면 `projectionId`와 `messageId`가 오고 구간 에러면 `phaseId`가 함께 온다.
|
|
580
594
|
|
|
581
595
|
| 에러 코드 | 고치는 법 |
|
|
@@ -607,7 +621,10 @@ FE가 부르는 BE 레포나 배포 매니페스트 레포처럼 지금 레포
|
|
|
607
621
|
| `PROJECTION_EDGE_NOT_FOUND`, `PROJECTION_EDGE_MISMATCH` | 메시지 `edge`를 그 두 노드를 잇는 지도 엣지로 고친다. 그런 엣지가 없으면 지도에 먼저 넣거나 `edge`를 뺀다 |
|
|
608
622
|
| `PROJECTION_BLOCK_NOT_FOUND`, `PROJECTION_BLOCK_SPLIT` | 메시지 `block`을 `blocks`의 id로 고치고 한 묶음의 메시지를 붙여 적는다 |
|
|
609
623
|
| `SOLID_MESSAGE_WITHOUT_EVIDENCE` | 가리킨 엣지나 자기 근거에 code나 spec이 없다. 근거를 찾아 달거나 점선으로 바꾼다 |
|
|
610
|
-
| `PROJECTION_EMPTY` | sequence와 dataflow에 메시지를 넣는다. 넣을 메시지가 없으면 그 그림을
|
|
624
|
+
| `PROJECTION_EMPTY` | sequence와 dataflow에 메시지를 넣는다. 넣을 메시지가 없으면 그 그림을 뺀다. lifecycle이면 가리킨 흐름 단계에 `state`를 단다. blueprint면 갈림길 말고 단계를 하나라도 둔다. er이면 `participants`에 테이블을 하나라도 둔다 |
|
|
625
|
+
| `PROJECTION_FLOW_NOT_FOUND` | lifecycle이나 blueprint의 `flow`를 `flows`에 있는 흐름 id로 고친다. 흐름이 아직 없으면 [Step 3.5](#step-35--도메인-흐름)대로 먼저 쓴다 |
|
|
626
|
+
| `COLUMN_REFERENCE_NOT_FOUND` | 컬럼 `references.table`을 지도에 있는 `db_table` id로 고친다. 대상이 `columns`를 적었으면 `references.column`도 그 안의 이름이어야 한다. 대상 테이블을 못 찾았으면 `references`를 빼고 질문으로 남긴다 |
|
|
627
|
+
| `INVALID_COLUMN_REFERENCE_KIND` | 외래 키는 `db_table`만 가리킨다. 저장소를 가리켰으면 그 안의 테이블 노드를 두고 다시 가리킨다 |
|
|
611
628
|
| `PROJECTION_SHAPE_FIELD` | 모양에 안 맞는 필드를 뺀다. [질문별 그림을 얹는다](#질문별-그림을-얹는다)의 모양별 설명을 본다 |
|
|
612
629
|
| `DUPLICATE_PHASE_ID` | 한 그림 안에서 구간 id가 겹친다. 다시 짓는다 |
|
|
613
630
|
| `PROJECTION_PHASE_MESSAGE_NOT_FOUND` | 구간 `from`이나 `to`를 그 그림의 메시지 id로 고친다. 다른 그림의 메시지는 못 가리킨다 |
|
|
@@ -653,7 +670,12 @@ render는 validate를 다시 하고 이전 실행 IR과 병합해 노드 id를
|
|
|
653
670
|
- `sharedHtmlPath`: private 근거의 위치와 인용을 빼고 출처 종류만 남긴 공유용. 다른 사람에게 넘길 때는 이 파일만 넘긴다
|
|
654
671
|
- `irPath`: 다음 실행의 출발점
|
|
655
672
|
- `levels`: 드릴다운으로 그렸을 때만 온다. 항목마다 `id`, `title`, `nodes`, `edges`가 있다. `id`는 `root`(전체), `service:<id>`, `feature:<id>`, `server:<id>`, `flow:<id>`, `group:<id>`, `view:<id>` 꼴이다
|
|
656
|
-
- `viewPaths`: 질문별 그림이 있을 때만 온다. 그림마다 `.gestalt/architecture/views/<view>.<그림 id>.json`에 그 그림과 가리킨 노드, 엣지, 질문만 따로 저장한 경로다. 다른 세션이 질문 하나의 답만 읽어 갈 때 이 파일을 건넨다
|
|
673
|
+
- `viewPaths`: 질문별 그림이 있을 때만 온다. 그림마다 `.gestalt/architecture/views/<view>.<그림 id>.json`에 그 그림과 가리킨 노드, 엣지, 질문만 따로 저장한 경로다. lifecycle과 blueprint는 가리킨 흐름(`flow`)을, er은 외래 키 대상 테이블과 `auto:fk:` 질문을 함께 싣는다. 다른 세션이 질문 하나의 답만 읽어 갈 때 이 파일을 건넨다
|
|
674
|
+
- `delta`: 이전 실행과 비교한 결과. 늘 온다. `status`는 넷 중 하나다
|
|
675
|
+
- `no_previous`: 비교할 이전 그림이 없다. 처음 그렸거나 저장된 이전 그림을 지금 규칙으로 읽지 못했다. 파일을 안 만든다
|
|
676
|
+
- `unchanged`: 그려지는 노드와 연결이 지난번과 같다. 지난 구조 변경 그림은 그대로 둔다
|
|
677
|
+
- `created`: 바뀐 게 있어 `<view>.delta.html`(본인용)과 `<view>.delta.shared.html`(공유용)을 썼다. `htmlPath`, `sharedHtmlPath`, 변경어별 건수 `changes`가 온다. 그림이 커서 바뀐 곳과 바로 이웃만 그렸으면 `scoped`도 온다. `changes` 키는 `ADDED` 생김, `REMOVED` 빠짐, `CHANGED` 변경, `MOVED` 이동, `REWIRED` 다시 이음이다. 그림 범례와 같은 말로 보고한다
|
|
678
|
+
- `failed`: 구조 변경 그림을 만들다 실패했다. 본 그림은 이미 저장됐고 `message`에 원인이 온다. 구조 변경 그림 경로는 오지 않는다
|
|
657
679
|
|
|
658
680
|
그려진 `service` 노드가 하나라도 있으면 HTML 한 장 안에 레벨을 나눠 담는다. 서비스가 없어도 `service` 없는 흐름이나 질문별 그림이 있으면, 또는 `infra`, `data`, `process` 팩 노드 사이에 parent가 있으면 레벨로 나눈다. 그 밖에는 `levels` 없이 평면 그림 한 장이다. deploy-path는 질문별 그림을 얹지 않으면 늘 평면이다.
|
|
659
681
|
|
|
@@ -679,6 +701,10 @@ render는 validate를 다시 하고 이전 실행 IR과 병합해 노드 id를
|
|
|
679
701
|
|
|
680
702
|
Step 4.5에서 클라우드를 조회했으면 어느 프로필로 언제 조회했는지 적는다. 만료로 조회를 못 했으면 "재로그인 필요"와 보여준 로그인 명령 모양을 적는다. 계정 ID는 보고에 적어도 되지만 공유본이나 커밋할 파일에는 옮기지 않는다.
|
|
681
703
|
|
|
704
|
+
**구조 변경은 `delta.status`대로 알린다.** `created`면 바뀐 건수를 변경어별로 한 줄에 적고 구조 변경 그림 경로를 준다 (예: "지난번보다 생김 2, 빠짐 1, 다시 이음 1. 구조 변경 그림은 `.gestalt/architecture/screen-chain.delta.html`"). 이 그림은 이전과 이번을 같은 좌표에 나란히 놓고 가운데 변경 목록을 둔다. 공유할 때는 `.delta.shared.html`을 넘긴다. `scoped`가 오면 전체 몇 개 중 몇 개만 그렸는지 덧붙인다. `unchanged`면 "지난번과 구조가 같다" 한 줄이면 된다. `no_previous`는 따로 알리지 않는다. 처음 그린 그림이면 당연한 결과다. `failed`면 본 그림은 정상으로 보고하고 "구조 변경 그림은 못 만들었다"와 `message`를 한 줄로 덧붙인다. 디스크에 남은 구조 변경 파일을 이번 결과처럼 건네지 않는다.
|
|
705
|
+
|
|
706
|
+
`warnings`에 `DELTA_OVER_BUDGET`이 오면 구조 변경 그림 한 장에 담기에 변경이 많다는 뜻이다. 그림은 그대로 썼다. 바뀐 영역을 나눠 단계별로 다시 그리기를 권한다.
|
|
707
|
+
|
|
682
708
|
Step 5에서 레포를 새로 받았으면 무엇을 어디에 받았는지 한 줄로 덧붙인다 (예: "`org/api-server`를 `~/.gestalt/architecture/clones/github.com/org/api-server`에 받았다").
|
|
683
709
|
|
|
684
710
|
## Step 9 — 재실행
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
- **조건에 따라 길이 나뉘는 자리는 갈림길 단계로 적는다.** `"kind": "decision"`을 달면 카드 대신 마름모로 그려진다. 단계 이름은 `품절 상품 포함?`처럼 묻는 꼴로 쓰고 나가는 전이마다 `condition`을 단다 (`예`, `아니오`). 같은 높이의 카드로 가는 길은 오른쪽 꼭짓점에서, 위아래로 다른 높이의 카드로 가는 길은 위나 아래 꼭짓점에서 나간다. 갈림길은 흐름이 끝나는 자리가 아니라서 `terminal: true`를 함께 달면 스키마 위반이다. validate는 나가는 길이 하나뿐인 갈림길에 `auto:branch`를, 근거는 있는데 `condition`도 `label`도 없는 나가는 전이에 `auto:condition` 질문을 남긴다.
|
|
29
29
|
- **되돌리기와 정정은 단계가 아니라 전이로 적는다.** 새 상태가 생기지 않고 앞 상태로 돌아가기만 해서다. "되돌리기" 카드를 따로 만들지 말고 `매장 취소 → 호출`처럼 돌아가는 화살표 하나로 쓴다. 누른 것과 조건은 나눠 적는다 (`"trigger": "되돌리기", "condition": "30분 이내"`). 그림에서는 두 카드 가까이로 지나가는 둥근 선에 ↩ 표시가 붙는다.
|
|
30
30
|
- **흐름이 끝나는 단계에는 `"terminal": true`를 단다.** 착석, 취소, 만료처럼 더 갈 곳이 없는 단계다. 나가는 전이가 없는데 이 표시도 없으면 validate가 `auto:dead-end` 질문을 남긴다. 미루기처럼 다시 줄로 돌아가는 단계가 선을 빠뜨렸을 때 그림이 거기서 끝난 것처럼 읽히는 걸 막으려는 표시다. 그 질문이 뜨면 끝 단계로 표시하기 전에 이어지는 전이를 코드에서 먼저 찾는다. 되돌릴 수 있는 취소처럼 끝 단계에서 나가는 전이가 있어도 된다.
|
|
31
|
+
- **끝 단계에는 어떻게 끝났는지를 `outcome`으로 단다.** 정상 완료는 `done`, 사용자나 매장이 그만둔 건 `cancel`, 만료나 오류로 끝난 건 `fail`이다. `terminal: true` 없이 `outcome`만 달면 스키마 위반이다. 흐름 그림은 이 값을 안 쓰고 [lifecycle 질문별 그림](./projections.md)이 끝 상태 카드 배지로 쓴다. 상태 흐름 그림을 얹을 거면 끝 단계에도 `state`를 단다.
|
|
31
32
|
- **정정도 같다.** 자동 노쇼를 착석으로 고치는 "노쇼 정정"은 `자동 노쇼 → 착석` 전이에 `actors: ["ops"]`다. 설명에 갈 수 있는 곳이 여럿 적혀 있으면 (착석이나 고객 취소) 전이도 그만큼 긋는다. validate가 이런 단계를 찾아 `auto:as-transition` 질문을 남긴다. 결제처럼 화면이 따로 있어 `refs`로 건너갈 일이 있는 단계는 카드로 둬도 된다.
|
|
32
33
|
- **행위자가 한 명이어도 된다.** 손님 혼자 화면을 넘기는 흐름이면 `actors`에 하나만 적는다. 그때는 줄을 가를 일이 없어 왼쪽 행위자 머리 칸을 걷고 그림 맨 위 띠에 행위자 칩 하나만 세운다.
|
|
33
34
|
- **여러 행위자가 할 수 있는 전이에는 `actors`를 단다.** 되돌리기를 손님도 매장도 할 수 있으면 `"actors": ["guest", "staff"]`다. 선 글자 옆에 행위자 이름이 붙는다. 행위자 줄은 그 사람이 하는 일을 놓는 자리라, 여럿이 하는 동작을 한 줄에 단계로 넣으면 틀린 그림이 된다.
|
|
@@ -27,5 +27,61 @@
|
|
|
27
27
|
- 안 적으면 render가 알아서 자른다. 맨 위 참여자가 지금 구간에서 처음 만나는 대상을 부르는 자리에서 새 구간이 열리고 구간 이름은 그 대상의 표시 이름이다. 그래서 모든 호출이 한 진입점을 거치는 흐름은 구간 하나로 뭉친다. 세션 모델이나 스킬 하나가 모든 호출을 내보내는 하네스 순서도가 그렇다. 같은 대상을 여러 번 오가는 흐름은 같은 이름 구간이 되풀이된다. 이런 흐름과 참여자가 많은 순서도에는 `phases`를 적는다.
|
|
28
28
|
- **dataflow**: `messages`만 쓴다. 데이터가 한 노드에서 다른 노드로 옮겨 가는 것 하나가 메시지 하나다. `blocks`와 메시지의 `reply`, `block`, `branch`는 쓰지 않는다.
|
|
29
29
|
- **compare**: `messages`는 빈 배열로 두고 `sides`에 견줄 두 묶음을 적는다. `{ id, label, nodes[] }` 둘이고 id는 달라야 한다. 그림은 "첫 묶음에만", "둘 다", "둘째 묶음에만" 세 열로 선다.
|
|
30
|
+
- **lifecycle**: `messages`는 빈 배열로 두고 `flow`에 `flows`의 흐름 id 하나를 적는다. `participants`, `blocks`, `phases`, `sides`는 쓰지 않는다. 흐름 단계의 `state`를 상태 하나씩으로 모아 다시 그린 그림이라 새로 적을 사실은 없다.
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{ "id": "queue-life", "shape": "lifecycle", "title": "줄서기 상태",
|
|
34
|
+
"question": "줄서기 항목은 어떤 상태를 거치나요?", "messages": [], "flow": "queue" }
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- 상태 카드는 세 띠에 선다. `main` 길의 상태는 맨 위 **진행 단계**, `side` 길에서만 닿는 상태는 가운데 **대기와 복구**, 끝 단계(`terminal: true`)의 상태는 맨 아래 **끝 상태**다. 정상 흐름이 끝나는 상태(`main`에 있고 `outcome`이 없거나 `done`)는 진행 단계 띠 끝에 남는다.
|
|
38
|
+
- `state`가 없는 단계는 그리지 않고 지나간다. 그 단계를 거치는 전이는 앞뒤 상태를 잇는 선 하나로 합쳐진다. 그래서 끝 단계에도 `state`를 달아야 끝 상태 카드가 선다. 같은 상태 안에서 앞으로만 가는 전이는 빠지고 같은 상태로 되돌아오는 전이만 자기 고리로 남는다.
|
|
39
|
+
- 선 글자는 합쳐진 전이마다 `condition`과 `trigger`를, 둘 다 없으면 `label`을 꺼내 쉼표로 잇는다. 하나도 없으면 도착 단계 이름을 흐린 기울임꼴로 빌려 쓴다. 되돌아가는 선에는 ↩가 붙는다.
|
|
40
|
+
- 끝 단계에 `outcome`을 달면 끝 상태 카드에 배지가 붙는다. `done`은 완료, `cancel`은 취소, `fail`은 실패다. 안 달면 "끝"이다. `outcome`은 끝 단계에만 단다.
|
|
41
|
+
- 한 장에 읽히는 양은 진행 단계 5개, 대기와 복구 2개, 끝 상태 2개, 상태 전체 9개, 전이 10개다. 넘어도 그리지만 validate가 `LIFECYCLE_OVER_BUDGET` 경고를 낸다. 세부 상태를 합치거나 흐름을 나눈다.
|
|
42
|
+
- **blueprint**: `messages`는 빈 배열로 두고 `flow`에 `flows`의 흐름 id 하나를 적는다. `participants`, `blocks`, `phases`, `sides`는 쓰지 않는다. 흐름 단계와 지도에 이미 적은 사실을 층으로 다시 나눈 그림이라 새로 적을 사실은 없다.
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{ "id": "queue-bp", "shape": "blueprint", "title": "줄서기 블루프린트",
|
|
46
|
+
"question": "손님이 줄을 서는 동안 뒤에서는 무엇이 일하나요?", "messages": [], "flow": "queue" }
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
- 열은 `main` 길의 단계다. 흐름 그림에서 같은 열에 서는 단계는 한 열로 묶이고 갈림길(`kind: "decision"`)과 `side` 길 단계는 빠진다. 열 머리는 그 열 단계의 `state` 이름이고 없으면 첫 단계 이름이다.
|
|
50
|
+
- 층은 위에서 아래로 **고객 행동**, **프론트스테이지**, **가시선**, **백스테이지**, **지원**이다. 흐름의 첫 `person` 행위자가 고객이라 그 단계는 고객 행동에 선다. 다른 사람의 단계는 프론트스테이지, 시스템과 에이전트의 단계는 백스테이지다.
|
|
51
|
+
- 단계 `refs`가 칸을 채운다. 화면과 스킬은 프론트스테이지, API와 MCP 도구는 백스테이지에 선다. 프론트스테이지 화면과 스킬이 `calls`로 부르는 API도 백스테이지에 더한다. 백스테이지 API를 처리하는 모듈이 닿는 테이블, 저장소, 외부 서비스, 큐, 잡은 지원에 선다.
|
|
52
|
+
- 근거 없는 엣지는 따라가지 않는다. 연결이 안 보이는 칸은 지어내지 않고 `—`로 비운다. 칸을 채우고 싶으면 단계에 `refs`를 달거나 지도에 근거와 함께 엣지를 넣는다. 층 사이에 선은 긋지 않는다.
|
|
53
|
+
- 칸 하나에 카드는 셋까지다. 나머지는 "+N"으로 접고 이름은 툴팁에 있다. 문서로만 닿은 카드는 테두리가 점선이다.
|
|
54
|
+
- 한 장에 읽히는 양은 단계 6열이다. 넘어도 그리지만 validate가 `BLUEPRINT_OVER_BUDGET` 경고를 낸다. 같은 화면에서 이어지는 단계를 합치거나 흐름을 나눈다.
|
|
55
|
+
- **er**: `messages`는 빈 배열로 두고 `participants`에 그릴 `db_table` id를 적는다. `blocks`, `phases`, `sides`, `flow`는 쓰지 않는다. 선은 테이블 노드 `columns`의 `references`에서 나온다. 그래서 그림을 얹기 전에 테이블마다 `columns`부터 채운다.
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{ "id": "order-schema", "shape": "er", "title": "주문 테이블 구조",
|
|
59
|
+
"question": "주문을 지우면 어떤 행이 같이 지워지나요?",
|
|
60
|
+
"participants": ["tbl:users", "tbl:orders", "tbl:order-items"], "messages": [] }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{ "id": "tbl:orders", "kind": "db_table", "label": "orders", "parent": "ds:main", "repo": "api",
|
|
65
|
+
"evidence": [{ "type": "code", "location": "api:db/migrations/003_orders.sql:1", "visibility": "public" }],
|
|
66
|
+
"columns": [
|
|
67
|
+
{ "name": "id", "type": "uuid", "pk": true },
|
|
68
|
+
{ "name": "user_id", "type": "uuid",
|
|
69
|
+
"references": { "table": "tbl:users", "column": "id", "onDelete": "CASCADE" },
|
|
70
|
+
"evidence": [{ "type": "code", "location": "api:db/migrations/003_orders.sql:4", "visibility": "public" }] }
|
|
71
|
+
] }
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
- 컬럼은 마이그레이션 파일, ORM 엔티티, 스키마 덤프에서 읽는다. 여러 곳이 다르면 마이그레이션을 따른다. 실제로 DB에 들어간 순서가 거기 있어서다.
|
|
75
|
+
- 테이블 상자에는 컬럼이 행 하나씩 서고 PK, FK, UQ, NULL 배지가 붙는다. 테이블 하나에 8행까지 보이고 나머지는 "컬럼 N개 더" 한 행으로 접는다. PK와 선이 붙는 컬럼이 먼저 남는다.
|
|
76
|
+
- 외래 키 선은 출발 컬럼 행에서 대상 컬럼 행으로 간다. 컬럼 `evidence`에 code나 spec이 있으면 실선, 문서 근거뿐이면 점선이다. 근거가 없으면 선을 긋지 않고 배지가 `FK?`로 서며 `auto:fk:<테이블 id>:<컬럼>` 질문이 생긴다. 이름이 `_id`로 끝난다고 짐작해 잇지 않는다.
|
|
77
|
+
- `onDelete`는 근거가 있는 외래 키에서만 선 위에 `ON DELETE …`로 보인다. 몇 대 몇인지는 그리지 않는다. 컬럼 정의만으로는 확실히 알 수 없어서다.
|
|
78
|
+
- `participants`에 없는 테이블을 가리키는 외래 키는 선 없이 FK 배지만 남는다. 그 테이블이 질문에 필요하면 `participants`에 더한다.
|
|
79
|
+
- 한 장에 읽히는 양은 테이블 5개, 한 테이블의 컬럼 8개, 외래 키 선 6개다. 넘어도 그리지만 validate가 `ER_OVER_BUDGET` 경고를 낸다. 질문에 걸린 테이블만 남기거나 그림을 나눈다.
|
|
80
|
+
- **흐름 그림, lifecycle, sequence 고르기**: 셋 다 "어떻게 진행되나"에 답하지만 묻는 기준이 다르다.
|
|
81
|
+
- "누가 무엇을 하나"면 흐름 그림이다. 행위자 줄마다 단계가 놓여 사람과 시스템이 일을 주고받는 자리가 보인다. `flows`만 쓰면 된다.
|
|
82
|
+
- "이 대상이 어떤 상태를 거쳐 어디서 끝나나"면 lifecycle이다. 행위자를 걷고 상태만 남겨 대기, 재시도, 취소, 실패가 정상 흐름과 어떻게 갈리는지 한눈에 보인다. 상태가 셋 이하면 흐름 그림 위쪽 상태 구간으로 충분하니 얹지 않는다.
|
|
83
|
+
- "어느 모듈이 무엇을 어떤 순서로 부르나"면 sequence다. 줄거리가 호출과 응답이다.
|
|
84
|
+
- **blueprint, dataflow, sequence 고르기**: "고객이 한 걸음 갈 때 화면 뒤에서 무엇이 일하나"면 blueprint다. 고객 단계가 열이라 단계마다 보이는 쪽과 안 보이는 쪽이 함께 읽힌다. 데이터가 어디서 와서 어디로 가는지면 dataflow이고 누가 누구를 어떤 순서로 부르는지면 sequence다. 둘은 선을 따라 읽는 그림이고 blueprint는 칸을 읽는 그림이다.
|
|
85
|
+
- **er, dataflow 고르기**: "어떤 테이블이 어떤 컬럼으로 서로를 가리키나", "이걸 지우면 무엇이 같이 지워지나"면 er이다. 테이블 안쪽 구조와 외래 키가 줄거리다. "데이터가 어느 모듈을 거쳐 어느 테이블에 쌓이나"면 dataflow다. 코드가 테이블을 읽고 쓰는 길을 따라가는 그림이라 컬럼은 안 나온다.
|
|
30
86
|
- 질문 하나에 그림 하나다. 질문이 여럿이면 그림도 여럿 단다.
|
|
31
87
|
- 하네스 레포는 묻지 않아도 진입 경로마다 순서도를 하나씩 얹는다. 자세한 건 [Step 3.5](../SKILL.md#step-35--도메인-흐름)의 하네스 흐름 항목에 있다.
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
2. **노드 id를 유지한다.** 같은 노드는 같은 id로 쓴다. render가 kind와 repo와 label이 같은 노드에 이전 id를 물려주긴 한다. 그런데 label을 바꾸면 다른 노드로 본다. 엔드포인트 label은 Step 3의 꼴을 그대로 지킨다. 사람이 읽을 이름을 고치고 싶으면 label 대신 `displayName`을 고친다.
|
|
3
3
|
3. **`previousSourcesUsed`를 먼저 간 본다.** `probeHit`가 `true`였던 소스부터 본다. 이번에도 `filter_tools`는 다시 거친다. 도구 이름이 같아도 이번 세션에 붙은 서버가 다를 수 있다.
|
|
4
4
|
4. **지난 실행 이후 바뀐 곳 주변만 다시 탐색한다.** `generatedAt` 이후의 `git log`와 `git diff`로 바뀐 파일을 뽑는다. 그 파일에 걸린 노드와 엣지만 근거 줄을 다시 확인한다. 안 바뀐 파일의 근거도 줄이 밀렸을 수 있으니 validate의 `CODE_EVIDENCE_NOT_FOUND`가 나면 그 근거는 다시 찾는다.
|
|
5
|
-
5. **질문별 그림은 지난 것을 다시 적지 않아도 된다.** 새 IR에 같은 id 그림이 없으면 render가 지난 그림을 이어 붙인다. 단 가리킨 노드와 엣지가 다 남아 있고 그림 id와 메시지 id가 이번 것과 안 겹칠 때만이다. 하나라도 어긋나면 버려지니 응답의 `viewPaths`에서 빠진 그림이 있는지 본다. 빠졌으면 지도를 고친 뒤 다시 적는다.
|
|
5
|
+
5. **질문별 그림은 지난 것을 다시 적지 않아도 된다.** 새 IR에 같은 id 그림이 없으면 render가 지난 그림을 이어 붙인다. 단 가리킨 노드와 엣지가 다 남아 있고 그림 id와 메시지 id가 이번 것과 안 겹칠 때만이다. lifecycle과 blueprint는 가리킨 흐름도 이번 IR `flows`에 있고 그릴 단계가 남아 있어야 한다(lifecycle은 `state`를 단 단계, blueprint는 갈림길이 아닌 단계). 흐름은 render가 지난 IR에서 이어받지 않으니 다시 적는다. er은 가리킨 노드가 이번에도 테이블(`db_table`)이어야 한다. 하나라도 어긋나면 버려지니 응답의 `viewPaths`에서 빠진 그림이 있는지 본다. 빠졌으면 지도를 고친 뒤 다시 적는다.
|
|
6
6
|
6. 답이 달린 지난 질문은 render가 물려준다. 답 안 달린 질문은 Step 7에서 다시 묻는다. `user` 근거로 정해진 기능영역 경계는 Step 3-1대로 그대로 둔다.
|
|
7
7
|
7. **화면 캡처는 지난 IR의 `capture`를 그대로 이어받는다.** 이미지는 읽지 말고 파일째 옮긴다. 4번에서 바뀐 파일로 뽑힌 화면이거나 `capture.commit` 이후 그 화면 코드가 바뀌었으면 낡았을 수 있다. 다시 찍을지 사용자에게 묻는다. 안 찍기로 하면 그대로 둔다.
|
|
8
|
+
8. **render 응답의 `delta`로 지난번과 무엇이 바뀌었는지 알린다.** render는 병합 전에 읽은 지난 IR과 이번 병합 결과를 id로 맞춰 생김(ADDED), 빠짐(REMOVED), 속성 변경(CHANGED), 부모나 계정, 구간 이동(MOVED), 연결 끝 변경(REWIRED)을 뽑는다. 2번처럼 label을 바꾼 노드는 빠짐과 생김 두 건으로 잡힌다. 이름만 고친 것을 변경 한 건으로 보이고 싶으면 `displayName`을 고친다. 알리는 법은 SKILL.md Step 8에 있다. 테이블 `columns`가 생기거나 빠지거나 바뀐 것도 그 테이블의 CHANGED 한 건에 컬럼 이름과 함께 실린다. 끝점이 바뀌어 짝지은 연결도 액션이 다르면 CHANGED와 REWIRED 두 건으로 잡힌다.
|
|
9
|
+
9. **테이블 `columns`는 render가 지난 IR에서 이어받지 않는다.** 이번 IR에 다시 적는다. 빠뜨리면 지운 컬럼과 구별이 안 돼 전부 빠짐으로 잡힌다. 마이그레이션이 늘었으면 새 파일만 읽어 지난 목록에 더한다.
|
|
@@ -344,9 +344,40 @@
|
|
|
344
344
|
"type": "array",
|
|
345
345
|
"items": { "type": "string", "minLength": 1 },
|
|
346
346
|
"description": "owning team or person from a sourced file such as CODEOWNERS or an ownership table; dropped from shared HTML"
|
|
347
|
+
},
|
|
348
|
+
"columns": {
|
|
349
|
+
"type": "array",
|
|
350
|
+
"items": { "$ref": "#/definitions/column" },
|
|
351
|
+
"description": "db_table only: columns read from migrations, ORM entities or schema files. Names must be unique within the table. The er projection draws them as rows"
|
|
347
352
|
}
|
|
348
353
|
}
|
|
349
354
|
},
|
|
355
|
+
"column": {
|
|
356
|
+
"type": "object",
|
|
357
|
+
"required": ["name"],
|
|
358
|
+
"properties": {
|
|
359
|
+
"name": { "type": "string", "minLength": 1 },
|
|
360
|
+
"type": { "type": "string", "minLength": 1, "description": "SQL type as written in the source" },
|
|
361
|
+
"pk": { "type": "boolean" },
|
|
362
|
+
"nullable": { "type": "boolean" },
|
|
363
|
+
"unique": { "type": "boolean" },
|
|
364
|
+
"references": {
|
|
365
|
+
"type": "object",
|
|
366
|
+
"required": ["table"],
|
|
367
|
+
"description": "foreign key target. The er projection draws a solid line when the column evidence has code or spec, a dashed line for weaker evidence, and no line without evidence",
|
|
368
|
+
"properties": {
|
|
369
|
+
"table": { "type": "string", "minLength": 1, "description": "id of a db_table node" },
|
|
370
|
+
"column": {
|
|
371
|
+
"type": "string",
|
|
372
|
+
"minLength": 1,
|
|
373
|
+
"description": "column name on the target table. Must exist when the target lists columns"
|
|
374
|
+
},
|
|
375
|
+
"onDelete": { "type": "string", "minLength": 1, "description": "ON DELETE action such as CASCADE or SET NULL" }
|
|
376
|
+
}
|
|
377
|
+
},
|
|
378
|
+
"evidence": { "type": "array", "items": { "$ref": "#/definitions/evidence" } }
|
|
379
|
+
}
|
|
380
|
+
},
|
|
350
381
|
"edge": {
|
|
351
382
|
"type": "object",
|
|
352
383
|
"required": ["id", "from", "to", "kind", "evidence", "lineStyle"],
|
|
@@ -484,6 +515,11 @@
|
|
|
484
515
|
"type": "boolean",
|
|
485
516
|
"description": "the flow may end here. Not allowed on a decision step"
|
|
486
517
|
},
|
|
518
|
+
"outcome": {
|
|
519
|
+
"type": "string",
|
|
520
|
+
"enum": ["done", "cancel", "fail"],
|
|
521
|
+
"description": "terminal steps only. How the flow ended. The lifecycle picture keeps done on the main rail and puts cancel and fail in the terminal band. Omit for done"
|
|
522
|
+
},
|
|
487
523
|
"refs": {
|
|
488
524
|
"type": "array",
|
|
489
525
|
"description": "ids of screen, endpoint, feature or micro_app nodes this step touches",
|
|
@@ -494,6 +530,9 @@
|
|
|
494
530
|
"if": { "properties": { "kind": { "const": "decision" } }, "required": ["kind"] },
|
|
495
531
|
"then": {
|
|
496
532
|
"not": { "properties": { "terminal": { "const": true } }, "required": ["terminal"] }
|
|
533
|
+
},
|
|
534
|
+
"dependencies": {
|
|
535
|
+
"outcome": { "properties": { "terminal": { "const": true } }, "required": ["terminal"] }
|
|
497
536
|
}
|
|
498
537
|
},
|
|
499
538
|
"flowTransition": {
|
|
@@ -595,17 +634,21 @@
|
|
|
595
634
|
"required": ["id", "shape", "title", "question", "messages"],
|
|
596
635
|
"properties": {
|
|
597
636
|
"id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$" },
|
|
598
|
-
"shape": { "type": "string", "enum": ["sequence", "dataflow", "compare"] },
|
|
637
|
+
"shape": { "type": "string", "enum": ["sequence", "dataflow", "compare", "lifecycle", "blueprint", "er"] },
|
|
599
638
|
"title": { "type": "string", "minLength": 1 },
|
|
600
639
|
"question": {
|
|
601
640
|
"type": "string",
|
|
602
641
|
"minLength": 1,
|
|
603
642
|
"description": "the one question this picture answers"
|
|
604
643
|
},
|
|
605
|
-
"participants": {
|
|
644
|
+
"participants": {
|
|
645
|
+
"type": "array",
|
|
646
|
+
"items": { "type": "string", "minLength": 1 },
|
|
647
|
+
"description": "for er, the db_table nodes to draw"
|
|
648
|
+
},
|
|
606
649
|
"messages": {
|
|
607
650
|
"type": "array",
|
|
608
|
-
"description": "lines of sequence and dataflow. Leave empty for compare",
|
|
651
|
+
"description": "lines of sequence and dataflow. Leave empty for compare, lifecycle, blueprint and er",
|
|
609
652
|
"items": { "$ref": "#/definitions/projectionMessage" }
|
|
610
653
|
},
|
|
611
654
|
"blocks": { "type": "array", "items": { "$ref": "#/definitions/projectionBlock" } },
|
|
@@ -619,6 +662,11 @@
|
|
|
619
662
|
"minItems": 1,
|
|
620
663
|
"description": "sequence only. Phases in message order, from and to inclusive, no overlap or gap. Leave out to split automatically",
|
|
621
664
|
"items": { "$ref": "#/definitions/projectionPhase" }
|
|
665
|
+
},
|
|
666
|
+
"flow": {
|
|
667
|
+
"type": "string",
|
|
668
|
+
"minLength": 1,
|
|
669
|
+
"description": "lifecycle and blueprint only. Id of the domain flow this picture draws. lifecycle draws its step states, blueprint draws its main steps as columns"
|
|
622
670
|
}
|
|
623
671
|
}
|
|
624
672
|
},
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import type { ArchitectureEdge, ArchitectureFlow, ArchitectureNode } from './types.js';
|
|
2
|
+
export type BlueprintRow = 'customer' | 'frontstage' | 'backstage' | 'support';
|
|
3
|
+
export declare const BLUEPRINT_ROWS: readonly BlueprintRow[];
|
|
4
|
+
export declare const BLUEPRINT_ROW_TEXT: Record<BlueprintRow, string>;
|
|
5
|
+
export declare const BLUEPRINT_VISIBILITY_TEXT = "\uAC00\uC2DC\uC120";
|
|
6
|
+
export declare const BLUEPRINT_VISIBILITY_NOTE = "\uC704\uB294 \uACE0\uAC1D\uC5D0\uAC8C \uBCF4\uC774\uACE0 \uC544\uB798\uB294 \uC548 \uBCF4\uC5EC\uC694";
|
|
7
|
+
/** 근거 있는 연결이 없는 칸에 찍는 글자. 비워 두면 그리다 빠뜨린 칸과 구분이 안 된다 */
|
|
8
|
+
export declare const BLUEPRINT_EMPTY_TEXT = "\u2014";
|
|
9
|
+
/** 칸 하나에 놓는 것. step은 흐름 단계, node는 지도 노드다. 둘 다 누르면 기존 서랍이 열린다 */
|
|
10
|
+
export interface BlueprintItem {
|
|
11
|
+
type: 'step' | 'node';
|
|
12
|
+
id: string;
|
|
13
|
+
/** 이 칸에 들어온 길이 모두 문서로만 확인됐으면 true. 카드 테두리를 점선으로 그린다 */
|
|
14
|
+
docOnly: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface BlueprintColumn {
|
|
17
|
+
/** 이 열에 선 정상 흐름 단계 id. 흐름에 적힌 순서다. 갈림길은 뺀다 */
|
|
18
|
+
steps: string[];
|
|
19
|
+
cells: Record<BlueprintRow, BlueprintItem[]>;
|
|
20
|
+
}
|
|
21
|
+
export interface BlueprintModel {
|
|
22
|
+
flowId: string;
|
|
23
|
+
/** 고객으로 본 행위자. actors의 첫 person이다. 없으면 고객 행동 층이 다 빈다 */
|
|
24
|
+
customer?: string;
|
|
25
|
+
columns: BlueprintColumn[];
|
|
26
|
+
/** 칸을 채우려고 따라간 엣지. 따로 저장하는 그림 파일에 함께 싣는다 */
|
|
27
|
+
edges: string[];
|
|
28
|
+
}
|
|
29
|
+
export interface BlueprintSource {
|
|
30
|
+
nodes: readonly ArchitectureNode[];
|
|
31
|
+
edges: readonly ArchitectureEdge[];
|
|
32
|
+
drawableNodeIds: ReadonlySet<string>;
|
|
33
|
+
drawableEdgeIds: ReadonlySet<string>;
|
|
34
|
+
drawableStepIds: ReadonlySet<string>;
|
|
35
|
+
drawableTransitionIds: ReadonlySet<string>;
|
|
36
|
+
}
|
|
37
|
+
export interface BlueprintCounts {
|
|
38
|
+
stages: number;
|
|
39
|
+
}
|
|
40
|
+
/** 블루프린트 한 장의 예산. 단계 4~6열이 한눈에 읽히는 폭이라 넘으면 경고로 흐름을 나누라고 알린다 */
|
|
41
|
+
export declare const BLUEPRINT_BUDGET: BlueprintCounts;
|
|
42
|
+
/** 칸 하나에 보이는 카드 수. 넘는 몫은 +N으로 접는다 */
|
|
43
|
+
export declare const BLUEPRINT_CARDS_PER_CELL = 3;
|
|
44
|
+
/**
|
|
45
|
+
* 흐름 하나를 블루프린트 칸으로 나눈다. 열은 정상 흐름 단계의 열이고 행은 층이다.
|
|
46
|
+
* 노드 칸은 단계 refs와 그려지는 엣지만 따라 채운다. 근거 있는 연결이 없으면 칸은 빈다
|
|
47
|
+
*/
|
|
48
|
+
export declare function deriveBlueprint(flow: ArchitectureFlow, src: BlueprintSource): BlueprintModel;
|
|
49
|
+
export declare function blueprintCounts(model: BlueprintModel): BlueprintCounts;
|
|
50
|
+
/** 예산을 넘은 항목을 사람이 읽는 글로. 안 넘었으면 빈 배열이다 */
|
|
51
|
+
export declare function blueprintOverBudget(counts: BlueprintCounts): string[];
|
|
52
|
+
/**
|
|
53
|
+
* 열 머리 글자. 단계에 상태가 있으면 그 상태 이름, 없으면 첫 단계 이름이다.
|
|
54
|
+
* 공유본에서는 가린 흐름을 넘겨 가린 글자가 찍힌다
|
|
55
|
+
*/
|
|
56
|
+
export declare function blueprintStageTitle(flow: ArchitectureFlow, col: BlueprintColumn): string;
|
|
57
|
+
export declare const BLUEPRINT_HEAD_W = 120;
|
|
58
|
+
export declare const BLUEPRINT_COL_W = 216;
|
|
59
|
+
export declare const BLUEPRINT_CARD_H = 44;
|
|
60
|
+
export type BlueprintLineRole = 'interaction' | 'visibility' | 'internal';
|
|
61
|
+
export interface BlueprintCardBox {
|
|
62
|
+
item: BlueprintItem;
|
|
63
|
+
x: number;
|
|
64
|
+
y: number;
|
|
65
|
+
width: number;
|
|
66
|
+
height: number;
|
|
67
|
+
}
|
|
68
|
+
export interface BlueprintCellBox {
|
|
69
|
+
row: BlueprintRow;
|
|
70
|
+
column: number;
|
|
71
|
+
x: number;
|
|
72
|
+
y: number;
|
|
73
|
+
width: number;
|
|
74
|
+
height: number;
|
|
75
|
+
cards: BlueprintCardBox[];
|
|
76
|
+
/** 접은 카드. 접은 것이 없으면 빈 배열이다 */
|
|
77
|
+
hidden: BlueprintItem[];
|
|
78
|
+
moreAt?: {
|
|
79
|
+
x: number;
|
|
80
|
+
y: number;
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export interface BlueprintLayout {
|
|
84
|
+
width: number;
|
|
85
|
+
height: number;
|
|
86
|
+
stages: {
|
|
87
|
+
x: number;
|
|
88
|
+
y: number;
|
|
89
|
+
width: number;
|
|
90
|
+
height: number;
|
|
91
|
+
}[];
|
|
92
|
+
rows: {
|
|
93
|
+
row: BlueprintRow;
|
|
94
|
+
y: number;
|
|
95
|
+
height: number;
|
|
96
|
+
}[];
|
|
97
|
+
lines: {
|
|
98
|
+
role: BlueprintLineRole;
|
|
99
|
+
y: number;
|
|
100
|
+
}[];
|
|
101
|
+
cells: BlueprintCellBox[];
|
|
102
|
+
}
|
|
103
|
+
/** 격자 좌표. 열은 같은 폭, 행 높이는 그 행에서 가장 많이 찬 칸에 맞춘다 */
|
|
104
|
+
export declare function computeBlueprintLayout(model: BlueprintModel): BlueprintLayout;
|
|
105
|
+
//# sourceMappingURL=blueprint-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blueprint-layout.d.ts","sourceRoot":"","sources":["../../../src/architecture/blueprint-layout.ts"],"names":[],"mappings":"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"}
|