@neobiotechlabs/neobiotech-dev-agent 0.1.7

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 (155) hide show
  1. package/.claude-plugin/marketplace.json +22 -0
  2. package/.claude-plugin/plugin.json +58 -0
  3. package/.mcp.json +14 -0
  4. package/README.md +442 -0
  5. package/dist/__tests__/adf.test.d.ts +1 -0
  6. package/dist/__tests__/adf.test.js +68 -0
  7. package/dist/__tests__/adf.test.js.map +1 -0
  8. package/dist/__tests__/annex-ii-template.test.d.ts +1 -0
  9. package/dist/__tests__/annex-ii-template.test.js +39 -0
  10. package/dist/__tests__/annex-ii-template.test.js.map +1 -0
  11. package/dist/__tests__/doc-render.test.d.ts +1 -0
  12. package/dist/__tests__/doc-render.test.js +93 -0
  13. package/dist/__tests__/doc-render.test.js.map +1 -0
  14. package/dist/__tests__/help.test.d.ts +1 -0
  15. package/dist/__tests__/help.test.js +31 -0
  16. package/dist/__tests__/help.test.js.map +1 -0
  17. package/dist/__tests__/jira-fields.test.d.ts +1 -0
  18. package/dist/__tests__/jira-fields.test.js +81 -0
  19. package/dist/__tests__/jira-fields.test.js.map +1 -0
  20. package/dist/__tests__/plugin-manifest.test.d.ts +1 -0
  21. package/dist/__tests__/plugin-manifest.test.js +91 -0
  22. package/dist/__tests__/plugin-manifest.test.js.map +1 -0
  23. package/dist/__tests__/setup.test.d.ts +1 -0
  24. package/dist/__tests__/setup.test.js +7 -0
  25. package/dist/__tests__/setup.test.js.map +1 -0
  26. package/dist/__tests__/sync-version.test.d.ts +1 -0
  27. package/dist/__tests__/sync-version.test.js +37 -0
  28. package/dist/__tests__/sync-version.test.js.map +1 -0
  29. package/dist/clients/risk-client.d.ts +17 -0
  30. package/dist/clients/risk-client.js +54 -0
  31. package/dist/clients/risk-client.js.map +1 -0
  32. package/dist/clients/xray-client.d.ts +34 -0
  33. package/dist/clients/xray-client.js +127 -0
  34. package/dist/clients/xray-client.js.map +1 -0
  35. package/dist/config/project-config.d.ts +14 -0
  36. package/dist/config/project-config.js +45 -0
  37. package/dist/config/project-config.js.map +1 -0
  38. package/dist/confluence-client.d.ts +16 -0
  39. package/dist/confluence-client.js +97 -0
  40. package/dist/confluence-client.js.map +1 -0
  41. package/dist/index.d.ts +2 -0
  42. package/dist/index.js +60 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/jira-client.d.ts +35 -0
  45. package/dist/jira-client.js +119 -0
  46. package/dist/jira-client.js.map +1 -0
  47. package/dist/tools/annex-ii-template.d.ts +30 -0
  48. package/dist/tools/annex-ii-template.js +129 -0
  49. package/dist/tools/annex-ii-template.js.map +1 -0
  50. package/dist/tools/confluence.d.ts +2 -0
  51. package/dist/tools/confluence.js +54 -0
  52. package/dist/tools/confluence.js.map +1 -0
  53. package/dist/tools/cvss.d.ts +2 -0
  54. package/dist/tools/cvss.js +59 -0
  55. package/dist/tools/cvss.js.map +1 -0
  56. package/dist/tools/doc-render.d.ts +2 -0
  57. package/dist/tools/doc-render.js +96 -0
  58. package/dist/tools/doc-render.js.map +1 -0
  59. package/dist/tools/doc-validation.d.ts +2 -0
  60. package/dist/tools/doc-validation.js +221 -0
  61. package/dist/tools/doc-validation.js.map +1 -0
  62. package/dist/tools/help-data.d.ts +7 -0
  63. package/dist/tools/help-data.js +144 -0
  64. package/dist/tools/help-data.js.map +1 -0
  65. package/dist/tools/help.d.ts +2 -0
  66. package/dist/tools/help.js +39 -0
  67. package/dist/tools/help.js.map +1 -0
  68. package/dist/tools/iec.d.ts +2 -0
  69. package/dist/tools/iec.js +203 -0
  70. package/dist/tools/iec.js.map +1 -0
  71. package/dist/tools/init.d.ts +2 -0
  72. package/dist/tools/init.js +38 -0
  73. package/dist/tools/init.js.map +1 -0
  74. package/dist/tools/jira-crud.d.ts +2 -0
  75. package/dist/tools/jira-crud.js +142 -0
  76. package/dist/tools/jira-crud.js.map +1 -0
  77. package/dist/tools/risk.d.ts +2 -0
  78. package/dist/tools/risk.js +172 -0
  79. package/dist/tools/risk.js.map +1 -0
  80. package/dist/tools/traceability.d.ts +2 -0
  81. package/dist/tools/traceability.js +85 -0
  82. package/dist/tools/traceability.js.map +1 -0
  83. package/dist/tools/types.d.ts +13 -0
  84. package/dist/tools/types.js +2 -0
  85. package/dist/tools/types.js.map +1 -0
  86. package/dist/tools/usability.d.ts +2 -0
  87. package/dist/tools/usability.js +149 -0
  88. package/dist/tools/usability.js.map +1 -0
  89. package/dist/tools/xray.d.ts +2 -0
  90. package/dist/tools/xray.js +35 -0
  91. package/dist/tools/xray.js.map +1 -0
  92. package/dist/utils/adf.d.ts +27 -0
  93. package/dist/utils/adf.js +104 -0
  94. package/dist/utils/adf.js.map +1 -0
  95. package/dist/utils/cvss.d.ts +15 -0
  96. package/dist/utils/cvss.js +86 -0
  97. package/dist/utils/cvss.js.map +1 -0
  98. package/dist/utils/doc-render.d.ts +28 -0
  99. package/dist/utils/doc-render.js +50 -0
  100. package/dist/utils/doc-render.js.map +1 -0
  101. package/dist/utils/jira-fields.d.ts +38 -0
  102. package/dist/utils/jira-fields.js +53 -0
  103. package/dist/utils/jira-fields.js.map +1 -0
  104. package/dist/utils/sync-version.d.ts +2 -0
  105. package/dist/utils/sync-version.js +20 -0
  106. package/dist/utils/sync-version.js.map +1 -0
  107. package/package.json +49 -0
  108. package/skills/doc-render/SKILL.md +79 -0
  109. package/vendor/dev-docs-templates/templates/dev_docs/plan_template.md +104 -0
  110. package/vendor/dev-docs-templates/templates/dev_docs/prd_template.md +110 -0
  111. package/vendor/dev-docs-templates/templates/dev_docs/spec_template.md +81 -0
  112. package/vendor/dev-docs-templates/templates/dev_docs/tasks_template.md +122 -0
  113. package/vendor/dev-docs-templates/templates/mdr_docs/CA/checklist-clinical-evaluation.md +81 -0
  114. package/vendor/dev-docs-templates/templates/mdr_docs/CA/checklist-gspr-mdr.md +403 -0
  115. package/vendor/dev-docs-templates/templates/mdr_docs/CA/clinical-evaluation-report.md +492 -0
  116. package/vendor/dev-docs-templates/templates/mdr_docs/CA/instructions-for-use.md +132 -0
  117. package/vendor/dev-docs-templates/templates/mdr_docs/CA/literature-evaluation-table.md +15 -0
  118. package/vendor/dev-docs-templates/templates/mdr_docs/CA/mdr-declaration-of-conformity.md +75 -0
  119. package/vendor/dev-docs-templates/templates/mdr_docs/CA/post-market-clinical-follow-up-plan.md +162 -0
  120. package/vendor/dev-docs-templates/templates/mdr_docs/CA/post-market-surveillance-plan.md +175 -0
  121. package/vendor/dev-docs-templates/templates/mdr_docs/CA/risk-management-cybersecurity-checklist.md +67 -0
  122. package/vendor/dev-docs-templates/templates/mdr_docs/CA/risk-management-report.md +111 -0
  123. package/vendor/dev-docs-templates/templates/mdr_docs/CA/usability-evaluation-report.md +70 -0
  124. package/vendor/dev-docs-templates/templates/mdr_docs/EA/clinical-evaluation-plan.md +154 -0
  125. package/vendor/dev-docs-templates/templates/mdr_docs/EA/list-of-hazard-related-use-scenarios.md +34 -0
  126. package/vendor/dev-docs-templates/templates/mdr_docs/EA/risk-table-fmea.md +155 -0
  127. package/vendor/dev-docs-templates/templates/mdr_docs/EA/software-architecture-description.md +307 -0
  128. package/vendor/dev-docs-templates/templates/mdr_docs/EA/software-requirements-list.md +156 -0
  129. package/vendor/dev-docs-templates/templates/mdr_docs/EA/soup-list.md +82 -0
  130. package/vendor/dev-docs-templates/templates/mdr_docs/EA/usability-evaluation-plan.md +103 -0
  131. package/vendor/dev-docs-templates/templates/mdr_docs/ER/global/bug-fixes-documentation-list.md +35 -0
  132. package/vendor/dev-docs-templates/templates/mdr_docs/ER/global/change-evaluation-list.md +100 -0
  133. package/vendor/dev-docs-templates/templates/mdr_docs/ER/global/list-of-known-anomalies.md +29 -0
  134. package/vendor/dev-docs-templates/templates/mdr_docs/ER/sprint/algorithm-validation-report.md +170 -0
  135. package/vendor/dev-docs-templates/templates/mdr_docs/ER/sprint/checklist-software-release.md +52 -0
  136. package/vendor/dev-docs-templates/templates/mdr_docs/ER/sprint/checklist-software-requirements-review.md +50 -0
  137. package/vendor/dev-docs-templates/templates/mdr_docs/ER/sprint/software-architecture-checklist.md +41 -0
  138. package/vendor/dev-docs-templates/templates/mdr_docs/ER/sprint/software-detailed-design.md +321 -0
  139. package/vendor/dev-docs-templates/templates/mdr_docs/ER/sprint/software-system-test-plan.md +155 -0
  140. package/vendor/dev-docs-templates/templates/mdr_docs/ER/sprint/usability-evaluation-protocol.md +63 -0
  141. package/vendor/dev-docs-templates/templates/mdr_docs/PA/intended-use.md +116 -0
  142. package/vendor/dev-docs-templates/templates/mdr_docs/PA/mdr-classification-document.md +114 -0
  143. package/vendor/dev-docs-templates/templates/mdr_docs/PA/risk-management-plan.md +198 -0
  144. package/vendor/dev-docs-templates/templates/mdr_docs/PA/software-development-maintenance-plan.md +225 -0
  145. package/vendor/dev-docs-templates/templates/mdr_docs/PA/system-requirements-spec.md +182 -0
  146. package/vendor/dev-docs-templates/templates/mdr_docs/global/information_security/information-security-controls.md +966 -0
  147. package/vendor/dev-docs-templates/templates/mdr_docs/global/information_security/information-security-policy-and-scope.md +99 -0
  148. package/vendor/dev-docs-templates/templates/mdr_docs/global/qms/quality-manual-policy-objectives.md +187 -0
  149. package/vendor/dev-docs-templates/templates/mdr_docs/global/qms/sop-capa.md +112 -0
  150. package/vendor/dev-docs-templates/templates/mdr_docs/global/qms/sop-change-management.md +128 -0
  151. package/vendor/dev-docs-templates/templates/mdr_docs/global/qms/sop-clinical-evaluation.md +102 -0
  152. package/vendor/dev-docs-templates/templates/mdr_docs/global/qms/sop-feedback-management.md +140 -0
  153. package/vendor/dev-docs-templates/templates/mdr_docs/global/qms/sop-integrated-software-development.md +361 -0
  154. package/vendor/dev-docs-templates/templates/mdr_docs/global/qms/sop-post-market-surveillance.md +159 -0
  155. package/vendor/dev-docs-templates/templates/mdr_docs/global/qms/sop-software-problem-resolution.md +99 -0
@@ -0,0 +1,129 @@
1
+ export const ANNEX_II_TEMPLATE = {
2
+ sections: [
3
+ {
4
+ id: 'device-description',
5
+ title: '1. 기기 설명 및 사양',
6
+ required: true,
7
+ description: '의료기기의 식별, 의도된 사용, 환자집단, 적응증, 임상적 이득',
8
+ matchKeywords: ['기기 설명', 'device description', 'Intended Use', '의도된 사용', '기기 사양', 'device specification'],
9
+ expectedSubTypes: ['Intended Use', 'System Requirement', 'Classification'],
10
+ requireApproval: true,
11
+ },
12
+ {
13
+ id: 'manufacturer-info',
14
+ title: '2. 제조자 정보',
15
+ required: true,
16
+ description: '제조자 명칭, 주소, 품질관리시스템, 수탁제조자 정보',
17
+ matchKeywords: ['제조자 정보', 'manufacturer information', '제조사 정보', 'manufacturer'],
18
+ requireApproval: true,
19
+ },
20
+ {
21
+ id: 'design-manufacturing',
22
+ title: '3. 설계 및 제조 정보',
23
+ required: true,
24
+ description: '설계 입력/출력, 아키텍처, 상세설계, 제조공정, 형상관리',
25
+ matchKeywords: ['설계', '제조', 'design', 'manufacturing', 'Architecture', 'Detailed Design', 'SAD', 'SDD', 'SDS', '설계 및 제조 정보'],
26
+ expectedSubTypes: ['Architecture', 'Detailed Design'],
27
+ requireApproval: true,
28
+ },
29
+ {
30
+ id: 'gspr',
31
+ title: '4. GSPR 준수성',
32
+ required: true,
33
+ description: 'MDR Annex I 일반안전성유효성요구사항(GSPR) 준수 증빙',
34
+ matchKeywords: ['GSPR', '일반안전성유효성', 'General Safety and Performance Requirements', 'Annex I', '안전성'],
35
+ requireApproval: true,
36
+ },
37
+ {
38
+ id: 'risk-management',
39
+ title: '5. 리스크 관리',
40
+ required: true,
41
+ description: '리스크 관리 보고서, Hazard 식별, 완화조치, 리스크 평가',
42
+ matchKeywords: ['리스크 관리', 'Risk Management', 'Hazard', 'Risk Report', '위험성', '리스크'],
43
+ expectedSubTypes: ['Hazard', 'Requirement'],
44
+ requireApproval: true,
45
+ },
46
+ {
47
+ id: 'verification-validation',
48
+ title: '6. 검증 및 검증 (V&V)',
49
+ required: true,
50
+ description: '테스트 계획, 테스트 결과, 검증 보고서, 유효성 확인',
51
+ matchKeywords: ['검증', 'V&V', 'Verification', 'Validation', '테스트', 'Test', 'V&V', 'verification and validation'],
52
+ expectedSubTypes: ['Test', 'Test Execution'],
53
+ requireApproval: true,
54
+ },
55
+ {
56
+ id: 'usability',
57
+ title: '7. 사용성 공학',
58
+ required: true,
59
+ description: 'IEC 62366-1 준수 사용성 공학 보고서, Use Specification, 시나리오, 검증',
60
+ matchKeywords: ['사용성', 'Usability', 'Use Specification', 'IEC 62366', '사용자 인터페이스', '사용 시나리오', 'usability engineering'],
61
+ expectedSubTypes: ['Use Scenario', 'Use Specification', 'Usability Validation'],
62
+ requireApproval: true,
63
+ },
64
+ {
65
+ id: 'pms',
66
+ title: '8. 시판후 감시 (PMS)',
67
+ required: true,
68
+ description: '시판후 감시 계획, 불만사항 처리, 현장안전정보시정조치(FSCA)',
69
+ matchKeywords: ['PMS', 'Post-Market Surveillance', '시판후 감시', 'post-market', '불만사항', 'FSCA'],
70
+ requireApproval: false,
71
+ },
72
+ {
73
+ id: 'ce',
74
+ title: '9. CE 마킹 및 준수 선언',
75
+ required: true,
76
+ description: 'CE 마킹 적용, EU 준수 선언서(EC DoC), NB 심사 보고서',
77
+ matchKeywords: ['CE 마킹', 'CE marking', '준수 선언', 'Declaration of Conformity', 'EC DoC', 'NB', 'Notified Body', '인증'],
78
+ requireApproval: true,
79
+ },
80
+ ],
81
+ };
82
+ export function matchSection(summary) {
83
+ const lowerSummary = summary.toLowerCase();
84
+ for (const section of ANNEX_II_TEMPLATE.sections) {
85
+ for (const keyword of section.matchKeywords) {
86
+ if (lowerSummary.includes(keyword.toLowerCase())) {
87
+ return section;
88
+ }
89
+ }
90
+ }
91
+ return undefined;
92
+ }
93
+ export function checkCompleteness(sections, tickets) {
94
+ const results = [];
95
+ for (const section of sections) {
96
+ const matchedTickets = tickets.filter(t => matchSection(t.summary)?.id === section.id);
97
+ if (matchedTickets.length === 0) {
98
+ results.push({
99
+ section,
100
+ status: 'missing',
101
+ tickets: [],
102
+ issues: [`필수 문서 누락: ${section.title}`],
103
+ });
104
+ }
105
+ else {
106
+ const issues = [];
107
+ const completedTickets = matchedTickets.filter(t => t.status === 'Done' || t.status === 'Closed' || t.status === 'Approved');
108
+ if (section.requireApproval && completedTickets.length === 0) {
109
+ issues.push('승인 상태가 아님 (Done/Closed/Approved 필요)');
110
+ }
111
+ if (section.expectedSubTypes && section.expectedSubTypes.length > 0) {
112
+ const foundSubTypes = new Set(matchedTickets.map(t => t.issuetype));
113
+ for (const expected of section.expectedSubTypes) {
114
+ if (!foundSubTypes.has(expected)) {
115
+ issues.push(`예상된 하위 타입 누락: ${expected}`);
116
+ }
117
+ }
118
+ }
119
+ results.push({
120
+ section,
121
+ status: issues.length > 0 ? 'incomplete' : 'found',
122
+ tickets: matchedTickets,
123
+ issues,
124
+ });
125
+ }
126
+ }
127
+ return results;
128
+ }
129
+ //# sourceMappingURL=annex-ii-template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annex-ii-template.js","sourceRoot":"","sources":["../../src/tools/annex-ii-template.ts"],"names":[],"mappings":"AAiBA,MAAM,CAAC,MAAM,iBAAiB,GAA+B;IAC3D,QAAQ,EAAE;QACR;YACE,EAAE,EAAE,oBAAoB;YACxB,KAAK,EAAE,eAAe;YACtB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,qCAAqC;YAClD,aAAa,EAAE,CAAC,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,sBAAsB,CAAC;YACzG,gBAAgB,EAAE,CAAC,cAAc,EAAE,oBAAoB,EAAE,gBAAgB,CAAC;YAC1E,eAAe,EAAE,IAAI;SACtB;QACD;YACE,EAAE,EAAE,mBAAmB;YACvB,KAAK,EAAE,WAAW;YAClB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,+BAA+B;YAC5C,aAAa,EAAE,CAAC,QAAQ,EAAE,0BAA0B,EAAE,QAAQ,EAAE,cAAc,CAAC;YAC/E,eAAe,EAAE,IAAI;SACtB;QACD;YACE,EAAE,EAAE,sBAAsB;YAC1B,KAAK,EAAE,eAAe;YACtB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,kCAAkC;YAC/C,aAAa,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,eAAe,EAAE,cAAc,EAAE,iBAAiB,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,CAAC;YAC5H,gBAAgB,EAAE,CAAC,cAAc,EAAE,iBAAiB,CAAC;YACrD,eAAe,EAAE,IAAI;SACtB;QACD;YACE,EAAE,EAAE,MAAM;YACV,KAAK,EAAE,aAAa;YACpB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,sCAAsC;YACnD,aAAa,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,6CAA6C,EAAE,SAAS,EAAE,KAAK,CAAC;YACpG,eAAe,EAAE,IAAI;SACtB;QACD;YACE,EAAE,EAAE,iBAAiB;YACrB,KAAK,EAAE,WAAW;YAClB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,qCAAqC;YAClD,aAAa,EAAE,CAAC,QAAQ,EAAE,iBAAiB,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,CAAC;YACnF,gBAAgB,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC;YAC3C,eAAe,EAAE,IAAI;SACtB;QACD;YACE,EAAE,EAAE,yBAAyB;YAC7B,KAAK,EAAE,kBAAkB;YACzB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,gCAAgC;YAC7C,aAAa,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,6BAA6B,CAAC;YAC/G,gBAAgB,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC;YAC5C,eAAe,EAAE,IAAI;SACtB;QACD;YACE,EAAE,EAAE,WAAW;YACf,KAAK,EAAE,WAAW;YAClB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,wDAAwD;YACrE,aAAa,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,uBAAuB,CAAC;YACtH,gBAAgB,EAAE,CAAC,cAAc,EAAE,mBAAmB,EAAE,sBAAsB,CAAC;YAC/E,eAAe,EAAE,IAAI;SACtB;QACD;YACE,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,iBAAiB;YACxB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,sCAAsC;YACnD,aAAa,EAAE,CAAC,KAAK,EAAE,0BAA0B,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,CAAC;YAC3F,eAAe,EAAE,KAAK;SACvB;QACD;YACE,EAAE,EAAE,IAAI;YACR,KAAK,EAAE,kBAAkB;YACzB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,wCAAwC;YACrD,aAAa,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,2BAA2B,EAAE,QAAQ,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,CAAC;YACnH,eAAe,EAAE,IAAI;SACtB;KACF;CACF,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAC3C,KAAK,MAAM,OAAO,IAAI,iBAAiB,CAAC,QAAQ,EAAE,CAAC;QACjD,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;YAC5C,IAAI,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;gBACjD,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,QAAsB,EACtB,OAAmF;IAEnF,MAAM,OAAO,GAAyB,EAAE,CAAC;IAEzC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,OAAO,CAAC,EAAE,CAAC,CAAC;QAEvF,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,IAAI,CAAC;gBACX,OAAO;gBACP,MAAM,EAAE,SAAS;gBACjB,OAAO,EAAE,EAAE;gBACX,MAAM,EAAE,CAAC,aAAa,OAAO,CAAC,KAAK,EAAE,CAAC;aACvC,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAa,EAAE,CAAC;YAC5B,MAAM,gBAAgB,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CACjD,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,UAAU,CACxE,CAAC;YAEF,IAAI,OAAO,CAAC,eAAe,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC7D,MAAM,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;YACrD,CAAC;YAED,IAAI,OAAO,CAAC,gBAAgB,IAAI,OAAO,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpE,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;gBACpE,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;oBAChD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;wBACjC,MAAM,CAAC,IAAI,CAAC,iBAAiB,QAAQ,EAAE,CAAC,CAAC;oBAC3C,CAAC;gBACH,CAAC;YACH,CAAC;YAED,OAAO,CAAC,IAAI,CAAC;gBACX,OAAO;gBACP,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO;gBAClD,OAAO,EAAE,cAAc;gBACvB,MAAM;aACP,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { ToolRegistrar } from './types.js';
2
+ export declare const registerConfluenceTools: ToolRegistrar;
@@ -0,0 +1,54 @@
1
+ import { z } from 'zod';
2
+ export const registerConfluenceTools = (ctx) => {
3
+ const { server, confluence } = ctx;
4
+ server.tool('confluence_get_page', 'Get a Confluence page by ID', {
5
+ page_id: z.string().describe('Page ID'),
6
+ expand: z.array(z.string()).optional().describe('Fields to expand (e.g. body.storage, version)'),
7
+ }, async ({ page_id, expand }) => {
8
+ const data = await confluence.getPage(page_id, expand);
9
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
10
+ });
11
+ server.tool('confluence_search', 'Search Confluence pages with CQL', {
12
+ cql: z.string().describe('CQL query string'),
13
+ limit: z.number().optional().default(25).describe('Maximum results'),
14
+ }, async ({ cql, limit }) => {
15
+ const data = await confluence.search(cql, limit);
16
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
17
+ });
18
+ server.tool('confluence_create_page', 'Create a new Confluence page', {
19
+ space_key: z.string().describe('Space key (e.g. PROJ)'),
20
+ title: z.string().describe('Page title'),
21
+ body: z.string().describe('Page content in Confluence storage format (HTML)'),
22
+ parent_id: z.string().optional().describe('Parent page ID'),
23
+ }, async ({ space_key, title, body, parent_id }) => {
24
+ const data = await confluence.createPage(space_key, title, body, parent_id);
25
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
26
+ });
27
+ server.tool('confluence_update_page', 'Update an existing Confluence page', {
28
+ page_id: z.string().describe('Page ID'),
29
+ title: z.string().describe('Page title'),
30
+ body: z.string().describe('Page content in Confluence storage format (HTML)'),
31
+ version: z.number().describe('Current version number of the page'),
32
+ }, async ({ page_id, title, body, version }) => {
33
+ const data = await confluence.updatePage(page_id, title, body, version);
34
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
35
+ });
36
+ server.tool('confluence_delete_page', 'Delete a Confluence page', {
37
+ page_id: z.string().describe('Page ID'),
38
+ }, async ({ page_id }) => {
39
+ await confluence.deletePage(page_id);
40
+ return { content: [{ type: 'text', text: `Page ${page_id} deleted` }] };
41
+ });
42
+ server.tool('confluence_get_spaces', 'List available Confluence spaces', {}, async () => {
43
+ const data = await confluence.getSpaces();
44
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
45
+ });
46
+ server.tool('confluence_get_page_children', 'Get child pages of a Confluence page', {
47
+ page_id: z.string().describe('Parent page ID'),
48
+ limit: z.number().optional().default(25).describe('Maximum results'),
49
+ }, async ({ page_id, limit }) => {
50
+ const data = await confluence.getPageChildren(page_id, limit);
51
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
52
+ });
53
+ };
54
+ //# sourceMappingURL=confluence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confluence.js","sourceRoot":"","sources":["../../src/tools/confluence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,CAAC,MAAM,uBAAuB,GAAkB,CAAC,GAAgB,EAAE,EAAE;IACzE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC;IAEnC,MAAM,CAAC,IAAI,CAAC,qBAAqB,EAAE,6BAA6B,EAAE;QAChE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;QACvC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;KACjG,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE;QAC/B,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACvD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,IAAI,CAAC,mBAAmB,EAAE,kCAAkC,EAAE;QACnE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QAC5C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,iBAAiB,CAAC;KACrE,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE;QAC1B,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACjD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE,8BAA8B,EAAE;QACpE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QACvD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;QACxC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kDAAkD,CAAC;QAC7E,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC;KAC5D,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE;QACjD,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAC5E,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE,oCAAoC,EAAE;QAC1E,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;QACvC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;QACxC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kDAAkD,CAAC;QAC7E,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;KACnE,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE;QAC7C,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QACxE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE,0BAA0B,EAAE;QAChE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;KACxC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;QACvB,MAAM,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACrC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,OAAO,UAAU,EAAE,CAAC,EAAE,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,IAAI,CAAC,uBAAuB,EAAE,kCAAkC,EAAE,EAAE,EAAE,KAAK,IAAI,EAAE;QACtF,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,SAAS,EAAE,CAAC;QAC1C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE,sCAAsC,EAAE;QAClF,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAC9C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,iBAAiB,CAAC;KACrE,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;QAC9B,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC9D,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAC9E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { ToolRegistrar } from './types.js';
2
+ export declare const registerCvssTools: ToolRegistrar;
@@ -0,0 +1,59 @@
1
+ import { z } from 'zod';
2
+ import { calculateCvssScore, buildCvssVector, parseCvssVector, validateMetrics, METRIC_LABELS } from '../utils/cvss.js';
3
+ export const registerCvssTools = (ctx) => {
4
+ const { server, jira } = ctx;
5
+ server.tool('cvss_calculate', 'Calculate CVSS v4.0 score and severity from metric values', {
6
+ metrics: z.record(z.string()).describe('CVSS v4.0 metrics as key-value pairs (e.g. {"AV":"N","AC":"L","PR":"N","UI":"N","VC":"H","VI":"L","VA":"N","SC":"N","SI":"N","SA":"N"})'),
7
+ }, async ({ metrics }) => {
8
+ const errors = validateMetrics(metrics);
9
+ if (errors.length > 0) {
10
+ return { content: [{ type: 'text', text: `Validation errors:\n${errors.join('\n')}` }] };
11
+ }
12
+ const vector = buildCvssVector(metrics);
13
+ const { score, severity } = calculateCvssScore(metrics);
14
+ const details = Object.entries(metrics).map(([k, v]) => ` ${k} = ${v} (${METRIC_LABELS[k] || k})`).join('\n');
15
+ return { content: [{ type: 'text', text: `CVSS Vector: ${vector}\nScore: ${score} (${severity})\n\nMetrics:\n${details}` }] };
16
+ });
17
+ server.tool('cvss_set_vector', 'Set CVSS v4.0 vector and score on a Vulnerability ticket', {
18
+ issue_key: z.string().describe('Vulnerability issue key'),
19
+ metrics: z.record(z.string()).optional().describe('CVSS v4.0 metrics as key-value pairs'),
20
+ vector: z.string().optional().describe('Full CVSS vector string (e.g. CVSS:4.0/AV:N/AC:L/...)'),
21
+ }, async ({ issue_key, metrics, vector: vectorStr }) => {
22
+ let finalMetrics;
23
+ if (vectorStr) {
24
+ finalMetrics = parseCvssVector(vectorStr);
25
+ }
26
+ else if (metrics) {
27
+ const errors = validateMetrics(metrics);
28
+ if (errors.length > 0)
29
+ return { content: [{ type: 'text', text: `Validation errors:\n${errors.join('\n')}` }] };
30
+ finalMetrics = metrics;
31
+ }
32
+ else {
33
+ return { content: [{ type: 'text', text: 'Provide either metrics or vector parameter' }] };
34
+ }
35
+ const vector = buildCvssVector(finalMetrics);
36
+ const { score, severity } = calculateCvssScore(finalMetrics);
37
+ const fields = {
38
+ customfield_10166: vector,
39
+ customfield_10167: `${score} / ${severity}`,
40
+ };
41
+ await jira.updateIssue(issue_key, fields);
42
+ return { content: [{ type: 'text', text: `Updated ${issue_key}\n Vector: ${vector}\n Score: ${score} (${severity})` }] };
43
+ });
44
+ server.tool('cvss_get_vector', 'Get CVSS vector and score from a Vulnerability ticket', {
45
+ issue_key: z.string().describe('Vulnerability issue key'),
46
+ }, async ({ issue_key }) => {
47
+ const data = await jira.getIssue(issue_key, ['summary', 'customfield_10166', 'customfield_10167']);
48
+ const f = data.fields;
49
+ const vector = f?.customfield_10166 || '';
50
+ const score = f?.customfield_10167 || '';
51
+ let details = '';
52
+ if (vector) {
53
+ const metrics = parseCvssVector(vector);
54
+ details = '\n\nMetrics:\n' + Object.entries(metrics).map(([k, v]) => ` ${k} = ${v} (${METRIC_LABELS[k] || k})`).join('\n');
55
+ }
56
+ return { content: [{ type: 'text', text: `${issue_key}: ${f?.summary}\nCVSS Vector: ${vector}\nCVSS Score: ${score}${details}` }] };
57
+ });
58
+ };
59
+ //# sourceMappingURL=cvss.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cvss.js","sourceRoot":"","sources":["../../src/tools/cvss.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { ToolRegistrar } from './types.js';
2
+ export declare const registerDocRenderTools: ToolRegistrar;
@@ -0,0 +1,96 @@
1
+ import { z } from 'zod';
2
+ import { readFileSync } from 'node:fs';
3
+ import { fileURLToPath } from 'node:url';
4
+ import path from 'node:path';
5
+ import { renderTemplate, TEMPLATE_PATHS, TEMPLATE_NAMES, TEMPLATE_VERSION } from '../utils/doc-render.js';
6
+ import { adfToMarkdown } from '../utils/adf.js';
7
+ // ESM에선 __dirname이 없음 — import.meta.url로 빌드 산출물 위치를 기준으로 경로 해석.
8
+ // dist/tools/doc-render.js → ../../vendor = repo 루트의 vendor/
9
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
+ const TEMPLATE_DIR = path.resolve(__dirname, '../../vendor/dev-docs-templates/templates');
11
+ // TEMPLATE_NAMES / TEMPLATE_PATHS 는 ../utils/doc-render.js 에서 (모드 기반 매핑)
12
+ export const registerDocRenderTools = (ctx) => {
13
+ const { server, jira } = ctx;
14
+ server.tool('doc_render', 'dev_docs(PRD/Spec/Plan/Tasks)·mdr_docs(intended-use 등) 템플릿을 모드 기반 결정적 렌더(freeform). 티켓 메타({TICKET_ID}/{DATE} 등)만 치환하고, 자유 텍스트/꺾쇠 placeholder/AI 지침은 consumer가 채우도록 반환. (레이어 ② — LLM 호출 없음)', {
15
+ template: z.enum(TEMPLATE_NAMES).describe('렌더할 템플릿: prd | spec | plan | tasks | intended_use'),
16
+ ticket_key: z.string().describe('Jira 티켓 키 (예: ER-123). description/메타 fetch에 사용'),
17
+ feature_slug: z.string().optional().describe('{FEATURE_SLUG} 치환용 (예: add-login). 미제공 시 placeholder로 남음'),
18
+ }, async ({ template, ticket_key, feature_slug }) => {
19
+ // 1. 티켓 fetch — 메타 + consumer 채우기용 본문 데이터
20
+ const data = await jira.getIssue(ticket_key, [
21
+ 'summary', 'description', 'issuetype', 'status', 'project', 'reporter', 'comment',
22
+ ]);
23
+ const reporter = data.fields?.reporter;
24
+ const ticket = {
25
+ key: data.key,
26
+ issuetype: data.fields?.issuetype?.name,
27
+ projectName: data.fields?.project?.name,
28
+ reporter: reporter?.displayName || reporter?.emailAddress,
29
+ };
30
+ // 2. 템플릿 로드 — 매핑 테이블에서 {path, mode}. 모드별 분기.
31
+ const entry = TEMPLATE_PATHS[template];
32
+ if (!entry) {
33
+ throw new Error(`알 수 없는 template: ${template}`);
34
+ }
35
+ if (entry.mode !== 'freeform') {
36
+ // table-map 등은 아직 미구현 — 도달 시 명시적 에러로 방어.
37
+ throw new Error(`template '${template}' (mode=${entry.mode}) 렌더는 아직 지원되지 않습니다. 현재 freeform만 구현됨.`);
38
+ }
39
+ const templatePath = path.join(TEMPLATE_DIR, entry.path);
40
+ const templateBody = readFileSync(templatePath, 'utf8');
41
+ // 3. 결정적 치환 (date는 주입 — 로직은 순수 유지)
42
+ const date = new Date().toISOString().split('T')[0];
43
+ const { rendered, unresolved } = renderTemplate({
44
+ template: templateBody,
45
+ ticket,
46
+ featureSlug: feature_slug,
47
+ date,
48
+ });
49
+ // 4. consumer용 데이터 패키징
50
+ const comments = (data.fields?.comment?.comments || [])
51
+ .slice(-5)
52
+ .map((c) => adfToMarkdown(c.body))
53
+ .filter((s) => s !== '');
54
+ const ticketData = {
55
+ key: data.key,
56
+ summary: data.fields?.summary,
57
+ status: data.fields?.status?.name,
58
+ issuetype: ticket.issuetype,
59
+ project: ticket.projectName,
60
+ reporter: ticket.reporter,
61
+ description: adfToMarkdown(data.fields?.description),
62
+ comments,
63
+ };
64
+ const text = [
65
+ `# doc_render — ${template} (티켓 ${ticket_key}, ${date})`,
66
+ '',
67
+ '## 렌더 메타 (consumer repo 저장 frontmatter용)',
68
+ '```yaml',
69
+ [
70
+ `doc: ${template}`,
71
+ `domain: ${entry.domain}`,
72
+ ...(entry.gate ? [`gate: ${entry.gate}`] : []),
73
+ `template_version: ${TEMPLATE_VERSION}`,
74
+ ].join('\n'),
75
+ '```',
76
+ '',
77
+ '## 렌더된 템플릿 (메타 변수 치환 완료 / 자유 텍스트는 placeholder 보존)',
78
+ '아래를 consumer가 채운 뒤 Write 도구로 docs/*.md 로 저장하세요.',
79
+ '```markdown',
80
+ rendered,
81
+ '```',
82
+ '',
83
+ '## 채워야 할 placeholder 변수 (티켓 데이터를 근거로 작성)',
84
+ unresolved.length > 0
85
+ ? unresolved.map((v) => `- {${v}}`).join('\n')
86
+ : '(없음 — 모든 변수가 치환됨)',
87
+ '',
88
+ '## 티켓 데이터 (빈칸 작성용 재료)',
89
+ '```json',
90
+ JSON.stringify(ticketData, null, 2),
91
+ '```',
92
+ ].join('\n');
93
+ return { content: [{ type: 'text', text }] };
94
+ });
95
+ };
96
+ //# sourceMappingURL=doc-render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doc-render.js","sourceRoot":"","sources":["../../src/tools/doc-render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { ToolRegistrar } from './types.js';
2
+ export declare const registerDocValidationTools: ToolRegistrar;
@@ -0,0 +1,221 @@
1
+ import { z } from 'zod';
2
+ import { textToAdf } from '../jira-client.js';
3
+ import { ANNEX_II_TEMPLATE, matchSection, checkCompleteness } from './annex-ii-template.js';
4
+ export const registerDocValidationTools = (ctx) => {
5
+ const { server, jira } = ctx;
6
+ server.tool('doc_create_from_template', 'Search existing Documents under a Gate, create missing ones per MDR Annex II template.', {
7
+ project_key: z.string().describe('Project key'),
8
+ gate_key: z.string().describe('Gate ticket key (PA or EA)'),
9
+ }, async ({ project_key, gate_key }) => {
10
+ // Get existing documents linked to the gate
11
+ const gateData = await jira.getIssue(gate_key, ['issuelinks', 'key', 'summary']);
12
+ const linkedIssues = [];
13
+ const links = gateData.fields?.issuelinks || [];
14
+ for (const link of links) {
15
+ if (link.outwardIssue) {
16
+ linkedIssues.push(link.outwardIssue.key);
17
+ }
18
+ }
19
+ // Get details of linked issues
20
+ const existingTickets = [];
21
+ for (const key of linkedIssues) {
22
+ try {
23
+ const data = await jira.getIssue(key, ['summary', 'issuetype']);
24
+ existingTickets.push({
25
+ key: data.key,
26
+ summary: data.fields.summary,
27
+ issuetype: data.fields.issuetype.name,
28
+ });
29
+ }
30
+ catch (e) {
31
+ // Ignore errors for deleted issues
32
+ }
33
+ }
34
+ // Find missing sections
35
+ const missingSections = [];
36
+ for (const section of ANNEX_II_TEMPLATE.sections) {
37
+ const exists = existingTickets.some(t => matchSection(t.summary)?.id === section.id);
38
+ if (!exists) {
39
+ missingSections.push(section);
40
+ }
41
+ }
42
+ // Create missing documents
43
+ const created = [];
44
+ for (const section of missingSections) {
45
+ const content = [
46
+ `# ${section.title}`,
47
+ '',
48
+ section.description,
49
+ '',
50
+ '## Content',
51
+ '[Document content to be filled]',
52
+ ].join('\n');
53
+ const issue = await jira.createIssue({
54
+ project: { key: project_key },
55
+ summary: `[${section.title}]`,
56
+ issuetype: { name: 'Document' },
57
+ description: textToAdf(content),
58
+ });
59
+ const issueKey = issue.key;
60
+ // Document blocks Gate
61
+ await jira.createLink('Blocks', gate_key, issueKey);
62
+ created.push({
63
+ key: issueKey,
64
+ sectionId: section.id,
65
+ title: section.title,
66
+ });
67
+ }
68
+ return { content: [{ type: 'text', text: JSON.stringify({
69
+ gate: gate_key,
70
+ existing_documents: existingTickets.length,
71
+ missing_sections: missingSections.map(s => s.id),
72
+ created_documents: created,
73
+ message: `${created.length} missing documents created from Annex II template.`,
74
+ }, null, 2) }] };
75
+ });
76
+ server.tool('doc_check_completeness', 'Query all Document tickets in project, run checkCompleteness against template, format report with ✅⚠️❌ icons.', {
77
+ project_key: z.string().describe('Project key'),
78
+ }, async ({ project_key }) => {
79
+ // Search all Document tickets in project
80
+ const searchResult = await jira.search(`project = ${project_key} AND issuetype = "Document"`, 100, ['summary', 'status', 'issuetype', 'key']);
81
+ const issues = searchResult.issues || [];
82
+ const tickets = issues.map((i) => ({
83
+ key: i.key,
84
+ summary: i.fields.summary,
85
+ status: i.fields.status.name,
86
+ issuetype: i.fields.issuetype.name,
87
+ }));
88
+ const results = checkCompleteness(ANNEX_II_TEMPLATE.sections, tickets);
89
+ // Format report
90
+ const lines = ['=== MDR Annex II 문서 완전성 검사 ===', ''];
91
+ for (const result of results) {
92
+ const icon = result.status === 'found' ? '✅' : result.status === 'missing' ? '❌' : '⚠️';
93
+ lines.push(`${icon} ${result.section.title} (${result.section.id})`);
94
+ if (result.tickets.length > 0) {
95
+ lines.push(` 티켓: ${result.tickets.map(t => `${t.key} (${t.status})`).join(', ')}`);
96
+ }
97
+ if (result.issues.length > 0) {
98
+ for (const issue of result.issues) {
99
+ lines.push(` - ${issue}`);
100
+ }
101
+ }
102
+ lines.push('');
103
+ }
104
+ const summary = {
105
+ total_sections: results.length,
106
+ found: results.filter((r) => r.status === 'found').length,
107
+ incomplete: results.filter((r) => r.status === 'incomplete').length,
108
+ missing: results.filter((r) => r.status === 'missing').length,
109
+ };
110
+ lines.push('=== 요약 ===');
111
+ lines.push(`총 섹션: ${summary.total_sections}`);
112
+ lines.push(`✅ 완료: ${summary.found}`);
113
+ lines.push(`⚠️ 불완전: ${summary.incomplete}`);
114
+ lines.push(`❌ 누락: ${summary.missing}`);
115
+ return { content: [{ type: 'text', text: lines.join('\n') }] };
116
+ });
117
+ server.tool('doc_generate_evidence', 'Generate evidence package for NB review: traceability matrix, risk matrix, V&V summary.', {
118
+ project_key: z.string().describe('Project key'),
119
+ }, async ({ project_key }) => {
120
+ // Get all issues with links for traceability
121
+ const issuesResult = await jira.search(`project = ${project_key}`, 500, ['key', 'summary', 'issuetype', 'status', 'issuelinks']);
122
+ const issues = issuesResult.issues || [];
123
+ // Build traceability map
124
+ const traceabilityMap = new Map();
125
+ for (const issue of issues) {
126
+ const links = [];
127
+ const issueLinks = issue.fields?.issuelinks || [];
128
+ for (const link of issueLinks) {
129
+ if (link.outwardIssue) {
130
+ links.push(`${link.type?.name || 'Relates'} → ${link.outwardIssue.key}`);
131
+ }
132
+ if (link.inwardIssue) {
133
+ links.push(`${link.type?.name || 'Relates'} ← ${link.inwardIssue.key}`);
134
+ }
135
+ }
136
+ traceabilityMap.set(issue.key, {
137
+ summary: issue.fields.summary,
138
+ type: issue.fields.issuetype.name,
139
+ links,
140
+ });
141
+ }
142
+ // Get Hazard tickets for risk matrix
143
+ const hazardResult = await jira.search(`project = ${project_key} AND issuetype = "Hazard"`, 100, ['key', 'summary', 'customfield_10375', 'customfield_10376', 'customfield_10377']);
144
+ const hazards = hazardResult.issues || [];
145
+ // Get Test tickets for V&V summary
146
+ const testResult = await jira.search(`project = ${project_key} AND issuetype = "Test"`, 100, ['key', 'summary', 'status']);
147
+ const tests = testResult.issues || [];
148
+ // Get Test Execution tickets for more V&V data
149
+ const testExecutionResult = await jira.search(`project = ${project_key} AND issuetype = "Test Execution"`, 100, ['key', 'summary', 'status']);
150
+ const testExecutions = testExecutionResult.issues || [];
151
+ // Format evidence package
152
+ const lines = [
153
+ '=== NB 심사용 증거 패키지 ===',
154
+ `생성일: ${new Date().toISOString().split('T')[0]}`,
155
+ `프로젝트: ${project_key}`,
156
+ '',
157
+ '## 1. 추적성 매트릭스 (Traceability Matrix)',
158
+ '',
159
+ '### Issue 추적성 (샘플 - 상위 20개)',
160
+ ];
161
+ let count = 0;
162
+ for (const [key, info] of traceabilityMap.entries()) {
163
+ if (count >= 20) {
164
+ lines.push(` ... (총 ${traceabilityMap.size}개 issue 중 ${count}개 표시)`);
165
+ break;
166
+ }
167
+ lines.push(`**${key}** [${info.type}]: ${info.summary.substring(0, 50)}...`);
168
+ if (info.links.length > 0) {
169
+ lines.push(` 링크: ${info.links.slice(0, 3).join(', ')}${info.links.length > 3 ? '...' : ''}`);
170
+ }
171
+ lines.push('');
172
+ count++;
173
+ }
174
+ lines.push('## 2. 리스크 매트릭스 (Risk Matrix)');
175
+ lines.push('');
176
+ if (hazards.length === 0) {
177
+ lines.push('(등록된 Hazard 없음)');
178
+ }
179
+ else {
180
+ for (const hazard of hazards.slice(0, 10)) {
181
+ const severity = hazard.fields?.customfield_10375?.value || 'N/A';
182
+ const p1 = hazard.fields?.customfield_10376?.value || 'N/A';
183
+ const p2 = hazard.fields?.customfield_10377?.value || 'N/A';
184
+ lines.push(`- ${hazard.key}: ${hazard.fields.summary.substring(0, 60)}...`);
185
+ lines.push(` Severity: ${severity}, P1: ${p1}, P2: ${p2}`);
186
+ lines.push('');
187
+ }
188
+ if (hazards.length > 10) {
189
+ lines.push(`... (총 ${hazards.length}개 Hazard 중 10개 표시)`);
190
+ }
191
+ }
192
+ lines.push('');
193
+ lines.push('## 3. V&V 요약 (Verification & Validation)');
194
+ lines.push('');
195
+ const allTests = [...tests, ...testExecutions];
196
+ if (allTests.length === 0) {
197
+ lines.push('(등록된 Test 없음)');
198
+ }
199
+ else {
200
+ const passed = allTests.filter((t) => t.fields.status.name === 'Passed' || t.fields.status.name === 'Done').length;
201
+ const failed = allTests.filter((t) => t.fields.status.name === 'Failed').length;
202
+ const pending = allTests.filter((t) => !['Passed', 'Done', 'Failed'].includes(t.fields.status.name)).length;
203
+ lines.push(`- 총 테스트: ${allTests.length}`);
204
+ lines.push(`- 통과: ${passed} (${Math.round(passed / allTests.length * 100)}%)`);
205
+ lines.push(`- 실패: ${failed}`);
206
+ lines.push(`- 대기: ${pending}`);
207
+ lines.push('');
208
+ lines.push('### 테스트 목록 (상위 10개)');
209
+ for (const test of allTests.slice(0, 10)) {
210
+ lines.push(`- ${test.key} [${test.fields.status.name}]: ${test.fields.summary.substring(0, 60)}...`);
211
+ }
212
+ if (allTests.length > 10) {
213
+ lines.push(`... (총 ${allTests.length}개 테스트 중 10개 표시)`);
214
+ }
215
+ }
216
+ lines.push('');
217
+ lines.push('=== 증거 패키지 생성 완료 ===');
218
+ return { content: [{ type: 'text', text: lines.join('\n') }] };
219
+ });
220
+ };
221
+ //# sourceMappingURL=doc-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doc-validation.js","sourceRoot":"","sources":["../../src/tools/doc-validation.ts"],"names":[],"mappings":"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"}