@tienne/gestalt 0.95.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.
Files changed (120) hide show
  1. package/CLAUDE.md +5 -3
  2. package/README.ko.md +1 -0
  3. package/README.md +1 -0
  4. package/dist/package.json +4 -3
  5. package/dist/plugin/skills/_shared/agent-model.md +5 -3
  6. package/dist/plugin/skills/_shared/proactive-routing.md +1 -0
  7. package/dist/plugin/skills/agent/SKILL.md +1 -1
  8. package/dist/plugin/skills/architecture/SKILL.md +31 -5
  9. package/dist/plugin/skills/architecture/references/domain-flow.md +1 -0
  10. package/dist/plugin/skills/architecture/references/projections.md +56 -0
  11. package/dist/plugin/skills/architecture/references/rerun.md +3 -1
  12. package/dist/plugin/skills/blast-radius/SKILL.md +1 -1
  13. package/dist/plugin/skills/build-graph/SKILL.md +1 -1
  14. package/dist/plugin/skills/doubt/SKILL.md +229 -0
  15. package/dist/plugin/skills/execute/SKILL.md +13 -1
  16. package/dist/plugin/skills/explain/SKILL.md +1 -1
  17. package/dist/plugin/skills/interview/SKILL.md +1 -1
  18. package/dist/plugin/skills/local-pr/SKILL.md +14 -1
  19. package/dist/plugin/skills/pr/SKILL.md +14 -1
  20. package/dist/plugin/skills/review/SKILL.md +14 -1
  21. package/dist/plugin/skills/review-loop/SKILL.md +13 -0
  22. package/dist/plugin/skills/review-reply/SKILL.md +13 -0
  23. package/dist/plugin/skills/ship/SKILL.md +14 -1
  24. package/dist/plugin/skills/solve/SKILL.md +1 -1
  25. package/dist/plugin/skills/spec/SKILL.md +1 -1
  26. package/dist/schemas/architecture-ir.schema.json +51 -3
  27. package/dist/schemas/gestalt.schema.json +12 -0
  28. package/dist/src/architecture/blueprint-layout.d.ts +105 -0
  29. package/dist/src/architecture/blueprint-layout.d.ts.map +1 -0
  30. package/dist/src/architecture/blueprint-layout.js +297 -0
  31. package/dist/src/architecture/blueprint-layout.js.map +1 -0
  32. package/dist/src/architecture/delta-renderer.d.ts +35 -0
  33. package/dist/src/architecture/delta-renderer.d.ts.map +1 -0
  34. package/dist/src/architecture/delta-renderer.js +329 -0
  35. package/dist/src/architecture/delta-renderer.js.map +1 -0
  36. package/dist/src/architecture/delta.d.ts +70 -0
  37. package/dist/src/architecture/delta.d.ts.map +1 -0
  38. package/dist/src/architecture/delta.js +342 -0
  39. package/dist/src/architecture/delta.js.map +1 -0
  40. package/dist/src/architecture/drilldown.d.ts +19 -1
  41. package/dist/src/architecture/drilldown.d.ts.map +1 -1
  42. package/dist/src/architecture/drilldown.js +5 -5
  43. package/dist/src/architecture/drilldown.js.map +1 -1
  44. package/dist/src/architecture/er-layout.d.ts +97 -0
  45. package/dist/src/architecture/er-layout.d.ts.map +1 -0
  46. package/dist/src/architecture/er-layout.js +344 -0
  47. package/dist/src/architecture/er-layout.js.map +1 -0
  48. package/dist/src/architecture/flow-layout.d.ts +22 -1
  49. package/dist/src/architecture/flow-layout.d.ts.map +1 -1
  50. package/dist/src/architecture/flow-layout.js +13 -9
  51. package/dist/src/architecture/flow-layout.js.map +1 -1
  52. package/dist/src/architecture/html-renderer.d.ts +4 -0
  53. package/dist/src/architecture/html-renderer.d.ts.map +1 -1
  54. package/dist/src/architecture/html-renderer.js +462 -20
  55. package/dist/src/architecture/html-renderer.js.map +1 -1
  56. package/dist/src/architecture/html-theme.d.ts +18 -0
  57. package/dist/src/architecture/html-theme.d.ts.map +1 -1
  58. package/dist/src/architecture/html-theme.js +101 -1
  59. package/dist/src/architecture/html-theme.js.map +1 -1
  60. package/dist/src/architecture/ir-schema.d.ts +358 -117
  61. package/dist/src/architecture/ir-schema.d.ts.map +1 -1
  62. package/dist/src/architecture/ir-schema.js +33 -1
  63. package/dist/src/architecture/ir-schema.js.map +1 -1
  64. package/dist/src/architecture/lifecycle-layout.d.ts +94 -0
  65. package/dist/src/architecture/lifecycle-layout.d.ts.map +1 -0
  66. package/dist/src/architecture/lifecycle-layout.js +471 -0
  67. package/dist/src/architecture/lifecycle-layout.js.map +1 -0
  68. package/dist/src/architecture/merge.d.ts.map +1 -1
  69. package/dist/src/architecture/merge.js +72 -2
  70. package/dist/src/architecture/merge.js.map +1 -1
  71. package/dist/src/architecture/store.d.ts +6 -1
  72. package/dist/src/architecture/store.d.ts.map +1 -1
  73. package/dist/src/architecture/store.js +75 -8
  74. package/dist/src/architecture/store.js.map +1 -1
  75. package/dist/src/architecture/types.d.ts +35 -3
  76. package/dist/src/architecture/types.d.ts.map +1 -1
  77. package/dist/src/architecture/types.js +13 -1
  78. package/dist/src/architecture/types.js.map +1 -1
  79. package/dist/src/architecture/validator.d.ts +27 -3
  80. package/dist/src/architecture/validator.d.ts.map +1 -1
  81. package/dist/src/architecture/validator.js +331 -8
  82. package/dist/src/architecture/validator.js.map +1 -1
  83. package/dist/src/core/config.d.ts +18 -0
  84. package/dist/src/core/config.d.ts.map +1 -1
  85. package/dist/src/core/config.js +14 -1
  86. package/dist/src/core/config.js.map +1 -1
  87. package/dist/src/core/hooks-env.d.ts +7 -2
  88. package/dist/src/core/hooks-env.d.ts.map +1 -1
  89. package/dist/src/core/hooks-env.js +7 -2
  90. package/dist/src/core/hooks-env.js.map +1 -1
  91. package/dist/src/mcp/tools/architecture-passthrough.d.ts.map +1 -1
  92. package/dist/src/mcp/tools/architecture-passthrough.js +91 -2
  93. package/dist/src/mcp/tools/architecture-passthrough.js.map +1 -1
  94. package/package.json +4 -3
  95. package/plugin/.codex-plugin/plugin.json +1 -1
  96. package/plugin/.mcp.json +1 -1
  97. package/plugin/mcp.json +1 -1
  98. package/plugin/skills/_shared/agent-model.md +5 -3
  99. package/plugin/skills/_shared/proactive-routing.md +1 -0
  100. package/plugin/skills/agent/SKILL.md +1 -1
  101. package/plugin/skills/architecture/SKILL.md +31 -5
  102. package/plugin/skills/architecture/references/domain-flow.md +1 -0
  103. package/plugin/skills/architecture/references/projections.md +56 -0
  104. package/plugin/skills/architecture/references/rerun.md +3 -1
  105. package/plugin/skills/blast-radius/SKILL.md +1 -1
  106. package/plugin/skills/build-graph/SKILL.md +1 -1
  107. package/plugin/skills/doubt/SKILL.md +229 -0
  108. package/plugin/skills/execute/SKILL.md +13 -1
  109. package/plugin/skills/explain/SKILL.md +1 -1
  110. package/plugin/skills/interview/SKILL.md +1 -1
  111. package/plugin/skills/local-pr/SKILL.md +14 -1
  112. package/plugin/skills/pr/SKILL.md +14 -1
  113. package/plugin/skills/review/SKILL.md +14 -1
  114. package/plugin/skills/review-loop/SKILL.md +13 -0
  115. package/plugin/skills/review-reply/SKILL.md +13 -0
  116. package/plugin/skills/ship/SKILL.md +14 -1
  117. package/plugin/skills/solve/SKILL.md +1 -1
  118. package/plugin/skills/spec/SKILL.md +1 -1
  119. package/schemas/architecture-ir.schema.json +51 -3
  120. package/schemas/gestalt.schema.json +12 -0
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: execute
3
3
  version: '1.3.0'
4
- description: 'Gestalt-driven execution planner that transforms a Spec into a validated ExecutionPlan. Requires a Spec that already exists. Given only a problem statement, use solve instead — it drives interview → spec → execute as one loop.'
4
+ description: '이미 있는 스펙(Spec)을 검증된 실행 계획(ExecutionPlan)으로 바꾸고 태스크 실행, 평가, 개선까지 진행한다. 스펙이 먼저 있어야 한다. 문제 설명만 있으면 solve를 쓴다. solve는 interview → spec → execute를 한 루프로 돈다.'
5
5
  triggers:
6
6
  - 'execute'
7
7
  - 'plan execution'
@@ -492,6 +492,18 @@ role_match/role_consensus로 얻은 `roleGuidance`를 참조해 태스크를 수
492
492
 
493
493
  ---
494
494
 
495
+ ## 단계를 건너뛰고 싶어질 때
496
+
497
+ Phase 3에 오면 태스크를 다 끝낸 뒤라 아래 같은 말이 떠오른다. 떠오르면 그 단계를 건너뛰지 말고 표의 오른쪽대로 간다.
498
+
499
+ | 변명 | 반박 |
500
+ | --- | --- |
501
+ | "lint는 오래 걸리니 빼고 test만 돌린다" | `structuralContext.commands`는 고치지 않고 그대로 실행한다. 명령이 빠지거나 다르면 서버가 제출을 거부한다. scripts에 없는 명령은 서버가 이미 뺐다. |
502
+ | "거부됐으니 이전 결과에 명령 문자열만 맞춰 다시 낸다" | `Submitted commands do not match`면 그 명령을 다시 실행해 새 종료 코드와 출력으로 제출한다. 문자열만 바꾼 제출은 돌리지 않은 결과를 돌린 것처럼 싣는 셈이다. |
503
+ | "실패한 테스트는 이번 변경과 상관없으니 `allPassed`를 true로 보낸다" | 종료 코드가 0이 아닌 명령이 있으면 `allPassed`를 true로 보내도 실패로 처리된다. 실패는 Flow A에서 다룬다. |
504
+ | "AC를 대부분 채웠으니 통과로 본다" | 완료 조건은 score ≥ 0.85와 goalAlignment ≥ 0.80 둘 다다. 하나라도 모자라면 Flow B로 간다. |
505
+ | "시간이 없으니 Evolve 없이 여기서 끝낸다" | Phase 3이 미달이면 서버는 `evolveContext`를 돌려준다. 여기서 멈추려면 `evolve`에 `terminateReason: "caller"`를 실어 직접 끝냈다는 걸 남긴다. |
506
+
495
507
  ## Phase 3 — Evaluate
496
508
 
497
509
  모든 태스크 완료 후 3-Call 평가 진행.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: explain
3
3
  version: "1.0.0"
4
- description: "개념이나 에러, 코드를 지정한 대상에게 맞춰 설명하고 explain-check로 판정한 뒤 걸리면 다시 쓰게 한다. '설명해줘/쉽게 풀어줘/이거 뭐야/기획팀한테 설명해줘' 요청 시 자동 발동. 소스 확보 → 대상 확정 → explainer 위임 → explain-check → 재시도. 판정까지 하는 스킬이다. 설명 문장만 빠르게 필요하면 explainer 에이전트를 직접 호출한다."
4
+ description: "개념이나 에러, 코드를 지정한 대상에게 맞춰 설명하고 explain-check로 판정한 뒤 걸리면 다시 쓰게 한다. '설명해줘/쉽게 풀어줘/ELI5/이거 뭐야/무슨 뜻이야/기획팀한테 설명해줘' 요청 시 자동 발동. 소스 확보 → 대상 확정 → explainer 위임 → explain-check → 재시도. 판정까지 하는 스킬이다. 설명 문장만 빠르게 필요하면 explainer 에이전트를 직접 호출한다."
5
5
  triggers:
6
6
  # 설명 요청
7
7
  - "설명해줘"
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: interview
3
3
  version: "1.2.0"
4
- description: "Gestalt-driven interview to clarify project requirements. Clarification only — it stops at a resolution score and does not produce a Spec. Use spec to turn a finished interview into a Spec, or solve to drive the whole loop without stopping between steps."
4
+ description: "질문을 주고받으며 프로젝트 요구사항을 명확하게 만드는(clarify requirements) Gestalt 인터뷰. 해상도 점수가 기준에 닿으면 멈추고 Spec은 만들지 않는다. 다음 단계는 spec이다. 단계 사이에 멈추지 않고 전체 루프를 돌리려면 solve를 쓴다."
5
5
  triggers:
6
6
  - "interview"
7
7
  - "clarify requirements"
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: local-pr
3
3
  version: "1.0.0"
4
- description: "레포 안에서 끝나는 PR 전용 스킬. 에이전트끼리 코드를 주고받을 때 쓴다. gh도 인증도 원격 왕복도 필요 없다. 만들기부터 리뷰, 머지, ref 정리까지 전부 다룬다. 사람에게 넘길 PR은 pr 스킬을 쓴다."
4
+ description: "레포 안에서 끝나는 로컬 PR 전용 스킬. 워커나 에이전트끼리 코드를 주고받을 때 gestalt pr 명령으로 쓴다. gh도 인증도 원격 왕복도 필요 없다. 만들기부터 리뷰, 머지, ref 정리까지 전부 다룬다. 사람에게 넘길 PR은 pr 스킬을 쓴다."
5
5
  triggers:
6
6
  - "로컬 PR"
7
7
  - "로컬로 PR"
@@ -70,6 +70,19 @@ git 저장소이기만 하면 된다. 인증도 원격도 안 본다.
70
70
 
71
71
  **`request_changes`가 나도 새 PR을 만들지 않는다.** 같은 PR에 라운드가 는다. `pr update --head <sha>`로 head를 옮기면 그 자리가 다음 라운드다.
72
72
 
73
+ ## 단계를 건너뛰고 싶어질 때
74
+
75
+ 승인 단계가 없는 스킬이라 아래 같은 말이 쉽게 통한다. 떠오르면 그 단계를 건너뛰지 말고 표의 오른쪽대로 간다.
76
+
77
+ | 변명 | 반박 |
78
+ | --- | --- |
79
+ | "diff를 읽어 보니 문제없어 체크아웃은 건너뛴다" | `pr diff`는 텍스트만 준다. 테스트가 무언가를 실제로 잡는지는 3단계에서 코드를 일부러 깨고 돌려봐야 안다. |
80
+ | "작성자가 깨고 돌려봤다고 했으니 그대로 믿는다" | 리뷰어가 직접 몇 군데를 깨서 테스트가 죽는지 확인한다. 작성자의 말은 검증 결과가 아니다. |
81
+ | "내가 만든 PR이라 내가 리뷰하는 게 빠르다" | 자기 PR은 자기가 리뷰하지 않는다. 다른 주체가 `pr checkout`으로 떼어내 직접 돌려보고 판정한다. |
82
+ | "`pnpm gate`가 실패했으니 바로 request-changes를 낸다" | base에서도 실패하는지 먼저 대조한다. 그 PR 때문이 아닐 수 있다. |
83
+ | "코멘트를 어투 규칙대로 썼으니 스캔은 생략한다" | 코드와 diff, PR 본문에 있던 말이 그대로 딸려오는 자리는 쓰는 쪽 자가점검으로 안 걸린다. 4단계 어투 검사는 필수다. |
84
+ | "미해결 스레드가 남았지만 승인 단계가 없으니 그냥 머지한다" | 머지는 되지만 미해결 수가 이벤트에 남는다. 남은 채로 머지할 이유가 있으면 그 이유를 코멘트로 먼저 남긴다. |
85
+
73
86
  ## 1단계: 만들기
74
87
 
75
88
  현재 브랜치의 변경으로 PR을 만든다. description은 `pr` 스킬의 0~4.5단계와 같은 방식으로 짓는다 — 레포 규칙을 먼저 보고 diff를 읽은 뒤 humanize를 거친다. 그 절차를 여기 다시 적지 않는다.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: pr
3
3
  version: "1.0.0"
4
- description: "GitHub PR 작성 전용 스킬. 레포 규칙을 먼저 탐색하고 미니 인터뷰로 컨텍스트를 수집한 뒤 diff 기반 PR description을 생성해 gh pr create로 제출한다. PR을 만드는 것까지가 범위다. 레포 안에서 끝나는 PR은 local-pr을 쓰고 이미 있는 코드를 검토받으려면 review를 쓴다."
4
+ description: "GitHub PR(pull request)을 만들어 올린다. 'PR 만들어줘/PR 써줘/PR 올려줘' 요청 시 쓴다. 레포 규칙을 먼저 탐색하고 미니 인터뷰로 컨텍스트를 수집한 뒤 diff 기반 PR 본문을 작성해 gh로 제출한다. PR을 만드는 것까지가 범위다. 로컬 PR은 local-pr, 이미 있는 코드 검토는 review를 쓴다."
5
5
  triggers:
6
6
  - "PR 작성"
7
7
  - "PR 만들어"
@@ -119,6 +119,19 @@ GitHub에 못 올려요 — {gh 인증이 없어요 / 원격이 없어요}.
119
119
  인증을 붙여주세요. 레포 안에서 끝낼 거면 로컬 PR로 만들게요.
120
120
  ```
121
121
 
122
+ ## 단계를 건너뛰고 싶어질 때
123
+
124
+ PR을 빨리 올리고 싶으면 아래 같은 말이 떠오릅니다. 떠오르면 그 단계를 건너뛰지 말고 표의 오른쪽대로 진행합니다.
125
+
126
+ | 변명 | 반박 |
127
+ | --- | --- |
128
+ | "이 레포엔 템플릿이 없을 테니 0단계는 건너뛴다" | 0단계는 스킵할 수 없습니다. 템플릿이 있으면 그 구조를 그대로 채워야 하는데 안 보고 쓰면 섹션을 임의로 짭니다. 템플릿이 없다는 것도 탐색해야 나오는 결과입니다. |
129
+ | "diff를 봤으니 변경 분석은 메인에서 바로 쓴다" | 3단계와 4.5단계는 서브에이전트에 맡깁니다. 메인에서 `ges_agent get`을 하면 룰북이 대화에 그대로 남습니다. |
130
+ | "흐름이 별로 안 바뀐 것 같으니 흐름 변화 섹션은 뺀다" | 흐름 변화는 반드시 넣습니다. 흐름이 안 바뀐 변경이면 에이전트가 남긴 `흐름 변화 없음` 표기를 그대로 씁니다. |
131
+ | "`changeContext`가 이미 humanize를 거쳤으니 4.5단계는 생략한다" | 4단계에서 새로 합성한 섹션은 윤문 없이 나온 문장입니다. 제목과 본문 전체를 4.5단계에서 다시 다듬습니다. |
132
+ | "윤문까지 했으니 어투 검사는 건너뛴다" | `changeContext`나 레포 템플릿에서 그대로 옮겨 붙은 문장은 윤문 에이전트의 자가 적용으로 안 걸립니다. 미리보기 전에 스캔합니다. |
133
+ | "PR 만들어 달라고 했으니 확인 없이 바로 올린다" | 5단계는 생성 전에 한 번 묻습니다. 사용자가 고칠 자리나 취소할 자리가 거기 있습니다. |
134
+
122
135
  ## Skill Instructions
123
136
 
124
137
  ### 0단계: 레포 규칙 탐색 (필수 — 스킵 불가)
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: review
3
3
  version: "1.0.0"
4
- description: "PR이나 브랜치, 커밋의 변경사항을 리뷰 에이전트(보안, 성능, 품질, 주석, 라이팅, 하네스)로 검토하고, humanize-monolith로 리포트를 다듬은 뒤, PR 대상이면 code-review-writer가 작성한 인라인 코멘트로 게시한다. 검토만 한다. PR을 새로 만드는 건 pr 스킬이고, 리뷰 관점 하나만 빠르게 물어보려면 security-reviewer 같은 에이전트를 직접 호출한다."
4
+ description: "PR이나 브랜치, 커밋의 diff를 코드 리뷰한다. '코드 리뷰해줘/PR 리뷰해줘/리뷰 코멘트 달아줘' 요청 시 쓴다. 보안, 성능, 품질, 주석, 라이팅, 하네스 리뷰 에이전트가 변경사항을 검토한다. PR 대상이면 다듬은 리포트를 PR에 인라인 코멘트로 게시한다. 주니어나 신입에게 설명하듯 쓰는 눈높이도 고를 수 있다. 검토만 한다. PR을 새로 만드는 건 pr 스킬이다. 리뷰 관점 하나만 빠르게 물어보려면 security-reviewer 같은 에이전트를 직접 호출한다."
5
5
  triggers:
6
6
  - "PR 리뷰"
7
7
  - "브랜치 리뷰"
@@ -173,6 +173,19 @@ id를 직접 주면 아래 1번의 첫 수단이 브랜치를 안 따지고 잡
173
173
  - `못 찾음`에는 알림이 따라붙을 수 있습니다. 가리는 법의 amend 분기에 걸린 PR이 그렇습니다. 판정은 `못 찾음` 그대로라 행이 늘지 않고 사용자만 한 줄 더 받습니다.
174
174
  - 4번은 로컬을 다시 안 봅니다. 그래서 4번 행의 결과가 전부 `none`입니다.
175
175
 
176
+ ## 단계를 건너뛰고 싶어질 때
177
+
178
+ 리뷰를 돌리다 보면 아래 같은 말이 떠오릅니다. 떠오르면 그 단계를 건너뛰지 말고 표의 오른쪽을 읽은 뒤 그대로 진행합니다.
179
+
180
+ | 변명 | 반박 |
181
+ | --- | --- |
182
+ | "사용자가 0단계에서 맥락을 다 줬으니 PR 본문은 안 읽어도 된다" | 1.15단계는 그래도 건너뛰지 않습니다. 사용자 말은 이번에 봐달라는 것이고 PR 본문은 작성자가 하려던 것입니다. 둘이 어긋나는 자리가 제일 볼 만한 자리인데 한쪽만 실으면 안 보입니다. |
183
+ | "리뷰어 여럿이 같은 자리를 짚었으니 제안 검증은 넘어가자" | 같은 의견이 여럿이어도 반영 결과가 맞다는 보증은 아닙니다. 라운드를 늘린 사례 87개 가운데 35개가 리뷰어 제안을 그대로 반영한 자리에서 생긴 새 문제였습니다. 3.7단계를 건너뛰는 건 이슈 초안이 하나도 없을 때와 서브에이전트가 실패했을 때뿐입니다. |
184
+ | "severity 낮은 이슈까지 검증할 필요는 없다" | 3.7단계는 severity와 상관없이 모든 이슈를 봅니다. 낮은 이슈의 제안도 반영하면 코드가 바뀝니다. |
185
+ | "방금 리뷰했으니 consensus는 아직 유효하다" | 유효한지는 `git rev-parse HEAD`와 PR head를 비교하면 알 수 있습니다. 그사이 커밋이 하나라도 붙었으면 stale이라 1단계부터 다시 돕니다. |
186
+ | "코멘트를 모아 한 번에 스캔하면 빠르다" | 한 덩어리로 스캔하면 코멘트 하나를 통째로 `>` 인용으로 감싸도 다른 코멘트 산문에 묻혀 안 걸립니다. 4.7단계 어투 검사는 코멘트마다 파일 하나로 떨궈 돌립니다. |
187
+ | "사용자가 리뷰를 맡겼으니 게시 확인은 생략한다" | 4.7단계 게시 확인은 코멘트를 다 쓴 뒤 한 번 묻는 자리입니다. 동의를 못 받으면 코멘트는 버리고 리포트만 보여줍니다. |
188
+
176
189
  ## Skill Instructions
177
190
 
178
191
  `repoRoot`가 주어지지 않으면 현재 작업 디렉토리를 절대 경로로 사용합니다.
@@ -193,6 +193,19 @@ state=$(gestalt review-loop state --pr <prNumber> --json) \
193
193
 
194
194
  규칙과 경계 조건은 `src/review-loop/`에 있고 `tests/unit/review-loop/`이 지킨다. 이 표를 고치려면 거기를 함께 고친다.
195
195
 
196
+ ## 단계를 건너뛰고 싶어질 때
197
+
198
+ 라운드를 기다리다 보면 아래 같은 말이 떠오른다. 떠오르면 그 단계를 건너뛰지 말고 표의 오른쪽대로 간다.
199
+
200
+ | 변명 | 반박 |
201
+ | --- | --- |
202
+ | "내 PR이지만 리뷰 루프는 돌려도 된다" | GitHub은 자기 PR에 approve를 안 받아서 이 루프의 종료 조건이 영원히 안 난다. Phase 0에서 멈추고 `ship`을 안내한다. |
203
+ | "상태 조회가 실패했지만 열린 스레드는 없었던 걸로 안다" | 조회 실패가 낸 `0`으로 approve가 나가는 자리가 2.2다. 조회가 실패하면 판정하지 않는다. |
204
+ | "이슈도 열린 스레드도 0개니 바로 approve를 게시한다" | ⓟ는 `approve-gate`부터 돌리고 확인을 받기 전에는 게시 명령을 실행하지 않는다. ⓢ에서 받은 자동 판정 동의는 approve를 명시한 게 아니다. |
205
+ | "escalate가 났지만 변경 요청은 남겨둔다" | 2.1은 `--request-changes`를 남기지 않는다. 라인 수정으로 안 풀리는 이탈이라 작성자가 무엇을 해야 할지 모른다. |
206
+ | "본문을 조금 다듬기만 했으니 어투 검사는 건너뛴다" | PR 본문과 diff에 있던 말이 그대로 딸려오는 자리는 자가점검으로 안 걸린다. 본문은 2.4 스캔을 거쳐야 2.5로 간다. 다시 써도 걸리면 무엇이 남았는지 알리고 게시할지 묻는다. |
207
+ | "작성자가 고쳤다고 답했으니 재리뷰 없이 approve한다" | Phase 4 판정은 상태 조회의 신호가 낸다. 답만 오고 코드가 그대로면 `REPLIES_ONLY`로 사람에게 간다. approve는 2.2에서 나온다. 재리뷰를 거치거나 ⓡ에서 사람이 답변을 받아들인 뒤라야 그 자리에 간다. |
208
+
196
209
  ## Phase 0 — 사전 점검
197
210
 
198
211
  ```bash
@@ -159,6 +159,19 @@ gh 인증이 되고 원격도 있는데 로컬 PR을 지정했으면 1번이 먼
159
159
  - `못 찾음`에는 알림이 따라붙을 수 있다. 가리는 법의 amend 분기에 걸린 PR이 그렇다. 판정은 `못 찾음` 그대로라 행이 늘지 않고 사용자만 한 줄 더 받는다.
160
160
  - 4번은 로컬을 다시 안 본다. 그래서 4번 행이 `local`이 아니라 `none`이다.
161
161
 
162
+ ## 단계를 건너뛰고 싶어질 때
163
+
164
+ 코멘트가 많거나 급하면 아래 같은 말이 떠오른다. 떠오르면 그 단계를 건너뛰지 말고 표의 오른쪽대로 간다.
165
+
166
+ | 변명 | 반박 |
167
+ | --- | --- |
168
+ | "REST로 코멘트를 받아왔으니 GraphQL 조회는 건너뛴다" | REST는 resolved 여부를 안 준다. 1단계를 GraphQL로 돌리지 않으면 이미 끝난 스레드에 답글을 다시 붙인다. |
169
+ | "코멘트에 붙은 diff로 충분하니 현재 코드는 안 읽는다" | `diff_hunk`는 리뷰 시점 스냅샷이다. 2단계에서 현재 코드를 읽어야 이미 바뀐 자리를 accept로 잘못 분류하지 않는다. |
170
+ | "처리 방향이 뻔하니 분류 승인은 넘어간다" | 3단계는 승인 없이 4단계로 안 넘어간다. 무엇을 받고 무엇을 반박할지는 사람이 정한다. |
171
+ | "한 줄 수정이라 커밋 해시는 나중에 붙인다" | 해시 없이 "반영했습니다"라고 쓰면 안 고친 걸 고쳤다고 쓰는 셈이다. accept인데 커밋이 없으면 답글을 쓰지 않고 유형을 되돌린다. |
172
+ | "푸시는 답글을 단 뒤에 해도 된다" | 푸시 전에는 리뷰어가 답글의 커밋 링크를 못 연다. 게시 전에 푸시 상태를 본다. |
173
+ | "답글 몇 줄은 직접 쓰는 게 빠르다" | 5단계 답글은 `code-review-responder`가 쓴다. 그 에이전트가 `author-voice.md`와 `ai-tell-quick-rules.md`를 읽고 쓰는 자리라 손으로 쓰면 그 룰이 안 걸린다. |
174
+
162
175
  ## 파이프라인
163
176
 
164
177
  ### 0단계: 대상 PR 식별 + 본인 PR 확인
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: ship
3
3
  version: "1.1.0"
4
- description: "로컬 PR로 리뷰를 수렴시킨 뒤 GitHub에 draft PR로 올리고 Copilot 리뷰까지 받아내는 출하 루프. 리뷰 → 대응 → 재리뷰를 이슈가 없어질 때까지 돌리고 그다음 단계로 넘어간다. 리뷰 한 번만 받으려면 review, PR만 만들려면 pr, 받은 리뷰에 답만 하려면 review-reply를 쓴다."
4
+ description: "내 브랜치를 출하한다. 레포 안 로컬 리뷰로 이슈를 수렴시킨 뒤 GitHub에 draft PR로 올리고 Copilot 리뷰까지 받아낸다. 리뷰를 통과할 때까지 대응을 반복하고 그다음 출하 단계로 넘어간다. 한 번만 검토받으려면 review, 새로 만들기만 하려면 pr, 받은 코멘트에 답만 하려면 review-reply를 쓴다."
5
5
  triggers:
6
6
  - "출하"
7
7
  - "ship"
@@ -204,6 +204,19 @@ Phase 3은 Phase 1에서 지은 목적을 그대로 쓰고 그 뒤 라운드에
204
204
 
205
205
  **상한에 걸려 루프가 안 끝났을 때는 ⓐ와 ⓒ로 넘어가지 않는다.** 남은 이슈를 정리해 보고하고 멈춘다.
206
206
 
207
+ ## 단계를 건너뛰고 싶어질 때
208
+
209
+ 라운드가 길어지면 아래 같은 말이 떠오른다. 떠오르면 그 단계를 건너뛰지 말고 표의 오른쪽대로 간다.
210
+
211
+ | 변명 | 반박 |
212
+ | --- | --- |
213
+ | "검증 명령은 Phase 0에서 승인받았으니 대조 없이 돌린다" | Phase 0에서 승인받은 건 명령 이름뿐이고 그 이름이 실행할 내용은 승인받지 않았다. 2.3과 4.5는 돌리기 전에 "검증 명령 대조" 절을 먼저 돈다. 4.5는 변경이 Copilot 코멘트에서 나와 더 그렇다. |
214
+ | "같은 이슈가 세 라운드째지만 한 번만 더 돌리면 풀릴 것 같다" | 2.5는 거기서 멈춘다. 자동 수정으로 안 풀리는 이슈라 더 돌려도 리뷰 에이전트와 검증만 다시 돈다. |
215
+ | "상한에 걸렸지만 남은 게 적으니 ⓐ로 넘긴다" | 2.6은 수렴하지 않은 채로 ⓐ에 안 간다. 남은 이슈를 정리해 보고하고 멈춘다. |
216
+ | "escalate가 났어도 결함 이슈부터 고치고 다시 판정받으면 된다" | 정합 심급이 Block인 채로 결함만 고치면 다음 라운드도 Block이다. 2.7은 2.3으로 안 내려가고 사람에게 묻는다. |
217
+ | "Copilot 코멘트가 사소하니 ⓑ 없이 ready로 간다" | 4.4의 수렴 조건은 새 코멘트 0건이다. 사소해 보여도 ⓑ에 올려 오탐이면 답글로 남긴다. |
218
+ | "승인은 앞에서 이미 받았다" | ⓐ와 ⓑ와 ⓒ는 외부로 나가는 순간마다 따로 받는다. ready 전환은 ⓒ에서 "바꾼다"를 고른 경우에만 한다. |
219
+
207
220
  ## 진행 패널
208
221
 
209
222
  라운드를 여러 번 도는 동안 사용자가 어디까지 왔는지 볼 자리를 만든다. `solve` 스킬과 같은 방식이다.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: solve
3
3
  version: "1.0.0"
4
- description: "제품 문제를 던지면 인터뷰 → 스펙 → 실행 루프를 자율로 드라이빙한다. 단계별로 멈춰 확인하고 싶으면 이 스킬이 아니다 — 요구사항만 정리하려면 interview, 스펙만 뽑으려면 spec, 이미 스펙이 있으면 execute를 쓴다."
4
+ description: "제품 문제를 던지면 인터뷰 → 스펙 → 실행 루프를 자율로 돌려 해결한다. 단계별로 멈춰 확인하고 싶으면 이 스킬이 아니다. 그럴 땐 interview와 spec을 따로 부른다. 스펙이 이미 있으면 execute를 쓴다."
5
5
  triggers:
6
6
  - "solve"
7
7
  - "문제 해결"
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: spec
3
3
  version: "1.2.0"
4
- description: "Generate a Spec specification from a completed interview. Requires an interview session id. Starting from a raw problem, run interview first, or use solve for the whole loop."
4
+ description: "끝난 인터뷰 세션으로 스펙(Spec) 문서를 만들어 낸다. 인터뷰 세션 id가 있어야 한다. 날것의 문제에서 시작하면 interview를 먼저 돌린다. 전체 루프는 solve를 쓴다."
5
5
  triggers:
6
6
  - "generate spec"
7
7
  - "create spec"
@@ -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": { "type": "array", "items": { "type": "string", "minLength": 1 } },
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
  },
@@ -167,6 +167,18 @@
167
167
  },
168
168
  "additionalProperties": false
169
169
  },
170
+ "webFetchCache": {
171
+ "type": "object",
172
+ "description": "Claude Code plugin hook that keeps WebFetch results on disk and replays them only when the origin answers 304 to a conditional request. Claude Code only",
173
+ "properties": {
174
+ "enabled": {
175
+ "type": "boolean",
176
+ "description": "Cache WebFetch results under ${XDG_CACHE_HOME:-~/.cache}/gestalt/webfetch-cache, outside the repo. Off by default because plugin hooks run in every repo (env: GESTALT_WEBFETCH_CACHE=1|0)",
177
+ "default": false
178
+ }
179
+ },
180
+ "additionalProperties": false
181
+ },
170
182
  "logLevel": {
171
183
  "type": "string",
172
184
  "enum": ["debug", "info", "warn", "error"],
@@ -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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"}