@neobiotechlabs/neobiotech-dev-agent 0.1.25 → 0.1.26

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.
@@ -10,7 +10,7 @@
10
10
  "source": "npm",
11
11
  "package": "@neobiotechlabs/neobiotech-dev-agent",
12
12
  "registry": "https://registry.npmjs.org",
13
- "version": "0.1.25"
13
+ "version": "0.1.26"
14
14
  },
15
15
  "description": "의료기기 SW 규제 개발 자동화 (Jira·Confluence·Risk·CVSS·Xray·IEC 62304/62366·MDR·문서 렌더)",
16
16
  "category": "medical-device",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neobiotech-dev-agent",
3
- "version": "0.1.25",
3
+ "version": "0.1.26",
4
4
  "displayName": "NeoBiotech Dev Agent (MedDev)",
5
5
  "description": "의료기기 SW 규제 개발 자동화 — Jira·Confluence·Risk·CVSS·Xray·IEC 62304/62366·MDR·문서 렌더",
6
6
  "author": {
package/README.md CHANGED
@@ -180,7 +180,7 @@ node ~/.claude/plugins/cache/neobiotech/neobiotech-dev-agent/<version>/dist/inde
180
180
  | `401`/`403` | 토큰/권한. Jira API 토큰 재발급, 프로젝트 권한·이슈타입 존재 여부 확인 |
181
181
  | 프로젝트 키가 인식 안 됨 | `jira_init_project` 미실행. consumer `CLAUDE.md`에 키가 있는지 확인 |
182
182
 
183
- ## 툴 목록 (55개)
183
+ ## 툴 목록 (56개)
184
184
 
185
185
  ### Jira 기본 CRUD (12)
186
186
 
@@ -293,7 +293,7 @@ IEC 62304 추적성 관리.
293
293
  |-----|------|
294
294
  | `doc_render` | dev_docs(PRD/Spec/Plan/Tasks)·mdr_docs(PA/EA gate 문서 전체) 템플릿 모드 기반(freeform) 결정적 렌더 — 메타만 치환, 자유 텍스트/AI 지침/빈 데이터 표는 consumer가 채움 |
295
295
 
296
- ### MDR 전문가 체크리스트 (2)
296
+ ### MDR 전문가 체크리스트 (3)
297
297
 
298
298
  역할별 규제 검토의 hard 기준(체크리스트)을 반환합니다. 판단은 아래 [MDR 전문가 에이전트](#mdr-전문가-에이전트-subagent) subagent가 담당합니다.
299
299
 
@@ -301,6 +301,7 @@ IEC 62304 추적성 관리.
301
301
  |-----|------|
302
302
  | `expert_get_regulatory_checklist` | MDR Regulatory Architect 검사 체크리스트 (Annex II / GSPR / intended use). phase 미사용 |
303
303
  | `expert_get_cybersecurity_checklist` | Cybersecurity Reviewer 검사 체크리스트 (IEC 81001-5-1 / FDA 2023 / AAMI TIR57-SW96). phase: design\|implementation\|verification\|postmarket |
304
+ | `expert_get_sw_architect_checklist` | SW Architect 검사 체크리스트 (IEC 62304 §5 / IEC 42010 / SOUP 선정·모니터링). scope: sad\|soup\|dd |
304
305
 
305
306
  ### 초기 설정 (1)
306
307
 
@@ -329,6 +330,7 @@ IEC 62304 추적성 관리.
329
330
 
330
331
  - `@mdr-cybersecurity-reviewer` — IEC 81001-5-1·FDA 2023 cybersecurity guidance·AAMI TIR57/SW96 보안 리뷰 (설계·구현·검증·운영 4단계)
331
332
  - `@mdr-regulatory-architect` — MDR Annex II·GSPR·intended use 규제 검토
333
+ - `@sw-architect` — IEC 62304 §5·IEC 42010 SW 아키텍처 품질 평가, SOUP 선정·모니터링 (EA 단계 SAD/SDD/SOUP List 평가, scope: sad|soup|dd)
332
334
 
333
335
  각 subagent는 대응하는 체크리스트 툴(`expert_get_*_checklist`)로 hard 기준을 먼저 로드한 뒤(STEP 1 강제), 기존 툴(jira/confluence/cvss/traceability)로 산출물을 교차 평가해 구조화된 리포트(필수항목 충족 여부 + 결함 + 권고)를 반환합니다. 체크리스트 기준 자체는 `src/tools/expert-checklists.ts`의 pure data로 결정적·재현 가능합니다.
334
336
 
@@ -0,0 +1,71 @@
1
+ ---
2
+ name: sw-architect
3
+ description: 의료기기 SW 아키텍처 품질 검토. IEC 62304 §5·IEC 42010·SOUP 선정 기준. 모듈 분해·인터페이스 contract·SOUP 선정/모니터링·의존성 방향·요구→아키텍처 매핑·trade-off 기록 평가. EA Gate 라이프사이클에서 SAD/SDD/SOUP List 리뷰 시점 또는 아키텍처 결정 직후 사용.
4
+ tools:
5
+ - mcp__neobiotech-dev-agent__expert_get_sw_architect_checklist
6
+ - mcp__neobiotech-dev-agent__jira_get_issue
7
+ - mcp__neobiotech-dev-agent__jira_get_links
8
+ - mcp__neobiotech-dev-agent__jira_search
9
+ - mcp__neobiotech-dev-agent__traceability_check
10
+ - mcp__neobiotech-dev-agent__traceability_find_missing
11
+ - mcp__neobiotech-dev-agent__confluence_get_page
12
+ - Read
13
+ - Grep
14
+ - Glob
15
+ model: inherit
16
+ ---
17
+
18
+ # Software Architect
19
+
20
+ 당신은 의료기기 SW 아키텍처 품질 평가자입니다. IEC 62304 §5(소프트웨어 시스템 시험 요구사항을 포함한 SW 시스템 아키텍처), IEC 42010(아키텍처 설명 관행), IEC 62304 §8.1.5 / IEC 81001-5-1 §7.1(SOUP 선정·모니터링)에 정통합니다.
21
+
22
+ ## 책임 범위 (명시)
23
+
24
+ 본 subagent는 **아키텍처 결정의 품질**을 평가합니다.
25
+ - ❌ MDR 규제 요건 자체 (intended use / GSPR 매핑) 평가 안 함 → `mdr-regulatory-architect`로 위임.
26
+ - ❌ 보안 통제 (인증·암호화·취약점 패치) 평가 안 함 → `mdr-cybersecurity-reviewer`로 위임.
27
+ - ❌ 문서 완결성 (placeholder 잔존·헤더 누락) 평가 안 함 → `document-content-reviewer`로 위임.
28
+ - ❌ chain 단절의 정량 보정 평가 안 함 → `traceability_find_missing` + consumer 결정.
29
+
30
+ 평가 대상 = EA Gate 8개 문서 중 **SAD · SDD · SOUP List**.
31
+
32
+ ## 수행 절차 (반드시 이 순서)
33
+
34
+ 1. consumer가 명시한 scope (sad | soup | dd | 미지정=전체) 인지.
35
+ 2. `expert_get_sw_architect_checklist(scope=...)` 호출해 검사 항목 로드. 이 단계를 건너뛰지 말 것.
36
+ 3. 각 항목의 `evidence.tools`가 지시하는 레이어1 툴로 산출물 조회.
37
+ 4. `passCriteria` 대조 → PASS / WARN(증거 부족·조회 실패) / FAIL 판정.
38
+ 5. 아래 출력 형식으로 구조화 리포트 반환.
39
+
40
+ ## 판정 규칙
41
+
42
+ - **PASS**: `passCriteria`가 관측 가능한 증거로 충족됨.
43
+ - **WARN**: 산출물 조회 불가 (권한·존재·링크 단절). "조회 불가"를 PASS로 처리하지 말 것.
44
+ - **FAIL**: 산출물은 존재하나 `passCriteria` 미충족.
45
+
46
+ ## 출력 형식
47
+
48
+ ```
49
+ ## SW Architect Review — [프로젝트/Gate 키, scope]
50
+
51
+ [상단] critical FAIL ≥1 시: "⛔ BLOCK — critical 미충족 N건"
52
+ critical FAIL 0 시: "✅ critical 통과 (major 미충족 M건)"
53
+
54
+ ### 항목별 판정
55
+ | id | scope | severity | 판정 | 근거 |
56
+ (각 항목: 근거에 티켓 키·필드·Confluence 페이지·링크 명시)
57
+
58
+ ### 권고 (soft 통찰)
59
+ (체크리스트 외 LLM trade-off 해석 — 모듈 경계 더 합리적일 수 있는 대안, 인터페이스에 빠진 케이스 등.
60
+ PASS/WARN/FAIL 판정과 무관. 의사결정 보조 한정.)
61
+
62
+ ### 다음 액션
63
+ (누락/미충족 항목에 대한 구체적 jira-mcp 툴 시그니처 제안 — 예: `jira_update_issue`로 SAD 본문 보강, `jira_create_link`로 SRS↔Architecture 매핑 추가)
64
+ ```
65
+
66
+ ## 주의
67
+
68
+ - **scope 미지정 시 잡음 경고**: 툴이 반환한 경고 텍스트가 있으면 미평가 항목 조회 불가 → WARN 누적 예상. consumer에게 적절한 scope(sad | soup | dd) 재호출 권고.
69
+ - **SAD/SOUP/DD 중 하나만 평가 시**: 다른 문서 미제출 평가 누락 시나리오 명시. "다른 문서 미평가" 라벨로 결과 표기.
70
+ - **SA-SOUP-SELECTION (critical)**: SOUP 항목별 rationale + alternatives + risk_assessment 누락 시 단일 FAIL로 BLOCK. SA-SOUP-SELECTION ↔ `mdr-cybersecurity-reviewer`의 CS-IMPL-SBOM·CS-PMS-RISK는 같은 SOUP 본문을 다른 layer에서 평가 — 합의 충돌 시 consumer가 verdict 비교 표로 가시화.
71
+ - **soft 통찰은 별도 박스**: verdict 경계 오염 방지. PASS/WARN/FAIL 결정과 무관함을 명시.
package/dist/index.js CHANGED
@@ -153272,17 +153272,33 @@ function normalizeObjectSchema(schema) {
153272
153272
  }
153273
153273
  return void 0;
153274
153274
  }
153275
+ function getDotPath(path3) {
153276
+ if (path3.length === 0) {
153277
+ return "object root";
153278
+ }
153279
+ return path3.reduce((acc, seg, index) => {
153280
+ if (index === 0) {
153281
+ return String(seg);
153282
+ }
153283
+ if (typeof seg === "number") {
153284
+ return `${acc}[${seg}]`;
153285
+ }
153286
+ return `${acc}.${seg}`;
153287
+ }, "");
153288
+ }
153275
153289
  function getParseErrorMessage(error2) {
153276
153290
  if (error2 && typeof error2 === "object") {
153291
+ if ("issues" in error2 && Array.isArray(error2.issues) && error2.issues.length > 0) {
153292
+ return error2.issues.map((i2) => {
153293
+ if (!i2.path?.length) {
153294
+ return i2.message;
153295
+ }
153296
+ return `${i2.message} at ${getDotPath(i2.path)}`;
153297
+ }).join("\n");
153298
+ }
153277
153299
  if ("message" in error2 && typeof error2.message === "string") {
153278
153300
  return error2.message;
153279
153301
  }
153280
- if ("issues" in error2 && Array.isArray(error2.issues) && error2.issues.length > 0) {
153281
- const firstIssue = error2.issues[0];
153282
- if (firstIssue && typeof firstIssue === "object" && "message" in firstIssue) {
153283
- return String(firstIssue.message);
153284
- }
153285
- }
153286
153302
  try {
153287
153303
  return JSON.stringify(error2);
153288
153304
  } catch {
@@ -158225,16 +158241,7 @@ var Server = class extends Protocol {
158225
158241
  if (!methodSchema) {
158226
158242
  throw new Error("Schema is missing a method literal");
158227
158243
  }
158228
- let methodValue;
158229
- if (isZ4Schema(methodSchema)) {
158230
- const v4Schema = methodSchema;
158231
- const v4Def = v4Schema._zod?.def;
158232
- methodValue = v4Def?.value ?? v4Schema.value;
158233
- } else {
158234
- const v3Schema = methodSchema;
158235
- const legacyDef = v3Schema._def;
158236
- methodValue = legacyDef?.value ?? v3Schema.value;
158237
- }
158244
+ const methodValue = getLiteralValue(methodSchema);
158238
158245
  if (typeof methodValue !== "string") {
158239
158246
  throw new Error("Schema method literal must be a string");
158240
158247
  }
@@ -159422,8 +159429,17 @@ var EMPTY_COMPLETION_RESULT = {
159422
159429
  import process2 from "process";
159423
159430
 
159424
159431
  // node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
159432
+ var STDIO_DEFAULT_MAX_BUFFER_SIZE = 10 * 1024 * 1024;
159425
159433
  var ReadBuffer = class {
159434
+ constructor(options) {
159435
+ this._maxBufferSize = options?.maxBufferSize ?? STDIO_DEFAULT_MAX_BUFFER_SIZE;
159436
+ }
159426
159437
  append(chunk) {
159438
+ const newSize = (this._buffer?.length ?? 0) + chunk.length;
159439
+ if (newSize > this._maxBufferSize) {
159440
+ this.clear();
159441
+ throw new Error(`ReadBuffer exceeded maximum size of ${this._maxBufferSize} bytes`);
159442
+ }
159427
159443
  this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;
159428
159444
  }
159429
159445
  readMessage() {
@@ -159451,18 +159467,24 @@ function serializeMessage(message) {
159451
159467
 
159452
159468
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
159453
159469
  var StdioServerTransport = class {
159454
- constructor(_stdin = process2.stdin, _stdout = process2.stdout) {
159470
+ constructor(_stdin = process2.stdin, _stdout = process2.stdout, options) {
159455
159471
  this._stdin = _stdin;
159456
159472
  this._stdout = _stdout;
159457
- this._readBuffer = new ReadBuffer();
159458
159473
  this._started = false;
159459
159474
  this._ondata = (chunk) => {
159460
- this._readBuffer.append(chunk);
159461
- this.processReadBuffer();
159475
+ try {
159476
+ this._readBuffer.append(chunk);
159477
+ this.processReadBuffer();
159478
+ } catch (error2) {
159479
+ this.onerror?.(error2);
159480
+ this.close().catch(() => {
159481
+ });
159482
+ }
159462
159483
  };
159463
159484
  this._onerror = (error2) => {
159464
159485
  this.onerror?.(error2);
159465
159486
  };
159487
+ this._readBuffer = new ReadBuffer({ maxBufferSize: options?.maxBufferSize });
159466
159488
  }
159467
159489
  /**
159468
159490
  * Starts listening for messages on stdin.
@@ -161073,6 +161095,11 @@ var TOOL_CATALOG = [
161073
161095
  description: "[\uC804\uBB38\uAC00\xB7\uBCF4\uC548] Cybersecurity Reviewer \uAC80\uC0AC \uCCB4\uD06C\uB9AC\uC2A4\uD2B8 \uBC18\uD658 (IEC 81001-5-1 / FDA 2023 / AAMI TIR57-SW96). phase: design|implementation|verification|postmarket",
161074
161096
  category: "MDR \uC804\uBB38\uAC00"
161075
161097
  },
161098
+ {
161099
+ name: "expert_get_sw_architect_checklist",
161100
+ description: "[\uC804\uBB38\uAC00\xB7SW \uC544\uD0A4\uD14D\uCC98] SW Architect \uAC80\uC0AC \uCCB4\uD06C\uB9AC\uC2A4\uD2B8 \uBC18\uD658 (IEC 62304 \xA75 / IEC 42010 / SOUP \uC120\uC815\xB7\uBAA8\uB2C8\uD130\uB9C1). scope: sad|soup|dd",
161101
+ category: "MDR \uC804\uBB38\uAC00"
161102
+ },
161076
161103
  // 문서 리뷰 soft verdict 평가 기준 (layer ② 데이터)
161077
161104
  {
161078
161105
  name: "review_get_criteria",
@@ -184937,11 +184964,106 @@ var EXPERT_CHECKLISTS = {
184937
184964
  }
184938
184965
  }
184939
184966
  ]
184967
+ },
184968
+ "sw-architect": {
184969
+ role: "sw-architect",
184970
+ title: "SW Architect \uCCB4\uD06C\uB9AC\uC2A4\uD2B8 (IEC 62304 \xA75 / IEC 42010 / SOUP \uC120\uC815\xB7\uBAA8\uB2C8\uD130\uB9C1)",
184971
+ items: [
184972
+ {
184973
+ id: "SA-MODULE-DECOMP",
184974
+ scope: ["sad"],
184975
+ standard: "IEC 62304 \xA75.1 / IEC 42010 \xA76.4",
184976
+ check: "SAD \uBAA8\uB4C8 \uBD84\uD574\uAC00 \uB2E8\uC77C \uCC45\uC784\xB7cohesion/coupling \uAD00\uC810\uC5D0\uC11C \uC815\uB2F9\uD654\uB418\uB294\uAC00",
184977
+ passCriteria: "SAD \uBCF8\uBB38\uC5D0 (a) \uBAA8\uB4C8\uBCC4 \uCC45\uC784 \uC815\uC758 (b) \uC758\uC874\uC131 \uADF8\uB798\uD504 \uB610\uB294 \uC758\uC874\uC131 \uBC29\uD5A5 \uD45C (c) cohesion/coupling \uBA85\uC2DC\uC801 \uADFC\uAC70",
184978
+ severity: "major",
184979
+ evidence: {
184980
+ tools: ["jira_get_issue", "confluence_get_page"]
184981
+ }
184982
+ },
184983
+ {
184984
+ id: "SA-INTERFACE-CONTRACT",
184985
+ scope: ["sad"],
184986
+ standard: "IEC 62304 \xA75.2 / IEC 42010 \xA77.1",
184987
+ check: "\uBAA8\uB4C8 \uAC04 \uC778\uD130\uD398\uC774\uC2A4 contract(\uC2DC\uADF8\uB2C8\uCC98\xB7\uC5D0\uB7EC\xB7\uB3D9\uC2DC\uC131\xB7\uB370\uC774\uD130 \uACC4\uC57D)\uAC00 \uC815\uC758\uB418\uC5C8\uB294\uAC00",
184988
+ passCriteria: 'SAD \uBCF8\uBB38\uC5D0 "Interface Definition" \uC139\uC158 \uC874\uC7AC + \uC2DC\uADF8\uB2C8\uCC98 \uD45C + \uC5D0\uB7EC \uCC98\uB9AC \uC815\uCC45 \uBA85\uC2DC',
184989
+ severity: "major",
184990
+ evidence: {
184991
+ tools: ["jira_get_issue", "confluence_get_page"]
184992
+ }
184993
+ },
184994
+ {
184995
+ id: "SA-DEPS-DIRECTION",
184996
+ scope: ["sad"],
184997
+ standard: "IEC 42010 \xA76.4 / \uC77C\uBC18 SW \uC544\uD0A4\uD14D\uCC98 \uAD00\uD589",
184998
+ check: "\uC758\uC874\uC131 \uBC29\uD5A5\uC774 \uC21C\uD658 \uC5C6\uC774 \uC778\uD130\uD398\uC774\uC2A4 \uC758\uC874\xB7\uAD6C\uD604 \uBE44\uC758\uC874\uC778\uAC00",
184999
+ passCriteria: "SAD \uC758\uC874\uC131 \uADF8\uB798\uD504/\uD45C\uC5D0\uC11C cycle \uBD80\uC7AC + \uC778\uD130\uD398\uC774\uC2A4 \uCD94\uC0C1\uD654 \uACC4\uCE35 \uBA85\uC2DC",
185000
+ severity: "major",
185001
+ evidence: {
185002
+ tools: ["jira_get_issue", "confluence_get_page"]
185003
+ }
185004
+ },
185005
+ {
185006
+ id: "SA-REQ-TO-ARCH",
185007
+ scope: ["sad"],
185008
+ standard: "IEC 62304 \xA75.1.3",
185009
+ check: "SRS\uC758 \uBAA8\uB4E0 functional/non-functional \uC694\uAD6C\uAC00 \uC544\uD0A4\uD14D\uCC98\uC5D0\uC11C \uB2E4\uB904\uC9C0\uB294\uAC00",
185010
+ passCriteria: "(a) traceability_check(Architecture) \uB2E8\uC808 \uC5C6\uC74C (b) \uBAA8\uB4E0 SRS Functional Requirement\uAC00 SAD \uCEF4\uD3EC\uB10C\uD2B8\uC5D0 \uB9E4\uD551\uB428",
185011
+ severity: "major",
185012
+ evidence: {
185013
+ tools: ["traceability_check", "jira_get_links", "jira_get_issue"]
185014
+ }
185015
+ },
185016
+ {
185017
+ id: "SA-TRADEOFF-DOCUMENTED",
185018
+ scope: ["sad"],
185019
+ standard: "IEC 42010 \xA78 / \uC77C\uBC18 ADR \uAD00\uD589",
185020
+ check: "\uD575\uC2EC \uC124\uACC4 \uACB0\uC815\uC758 trade-off(\uB300\uC548 \uBE44\uAD50\xB7\uC120\uC815 \uC0AC\uC720)\uAC00 \uAE30\uB85D\uB418\uC5B4 \uC788\uB294\uAC00",
185021
+ passCriteria: "SAD \uBCF8\uBB38 \uB610\uB294 ADR \uD2F0\uCF13\uC5D0 (a) \uACB0\uC815 \uC694\uC57D (b) \uAC80\uD1A0\uD55C \uB300\uC548 \u2265 2 (c) \uC120\uC815 \uC0AC\uC720 (d) trade-off \uD45C",
185022
+ severity: "minor",
185023
+ evidence: {
185024
+ tools: ["jira_search", "jira_get_issue"]
185025
+ }
185026
+ },
185027
+ {
185028
+ id: "SA-SOUP-SELECTION",
185029
+ scope: ["soup"],
185030
+ standard: "IEC 62304 \xA78.1.5 / IEC 81001-5-1 \xA77.1",
185031
+ check: "\uAC01 SOUP \uC120\uC815\uC5D0 (a) \uC120\uC815 \uC0AC\uC720 (b) \uAC80\uD1A0\uD55C \uB300\uC548 (c) SOUP \uB9AC\uC2A4\uD06C \uD3C9\uAC00(\uACF5\uAE09 \uC548\uC815\uC131\xB7\uB77C\uC774\uC120\uC2A4\xB7\uCDE8\uC57D\uC810)\uAC00 \uC788\uB294\uAC00",
185032
+ passCriteria: "SOUP List \uD56D\uBAA9\uBCC4 rationale + alternatives + risk_assessment \uD544\uB4DC/\uC139\uC158 \uC874\uC7AC",
185033
+ severity: "critical",
185034
+ evidence: {
185035
+ tools: ["jira_get_issue", "confluence_get_page"]
185036
+ }
185037
+ },
185038
+ {
185039
+ id: "SA-SOUP-MONITORING",
185040
+ scope: ["soup"],
185041
+ standard: "IEC 81001-5-1 \xA77.1 / FDA 2023",
185042
+ check: "SOUP \uBCC0\uACBD \uAC10\uC9C0\xB7\uCDE8\uC57D\uC810 \uBAA8\uB2C8\uD130\uB9C1\xB7\uC5C5\uB370\uC774\uD2B8 \uC815\uCC45\uC774 \uC815\uC758\uB418\uC5C8\uB294\uAC00",
185043
+ passCriteria: "SOUP List\uC5D0 monitoring_plan \uC139\uC158 + \uCDE8\uC57D\uC810 \uBAA8\uB2C8\uD130\uB9C1 \uC8FC\uCCB4/\uB3C4\uAD6C \uBA85\uC2DC + \uC5C5\uB370\uC774\uD2B8 \uC815\uCC45",
185044
+ severity: "major",
185045
+ evidence: {
185046
+ tools: ["jira_get_issue", "confluence_get_page"]
185047
+ }
185048
+ },
185049
+ {
185050
+ id: "SA-DETAIL-TO-ARCH",
185051
+ scope: ["dd"],
185052
+ standard: "IEC 62304 \xA75.4",
185053
+ check: "DD\uAC00 \uC544\uD0A4\uD14D\uCC98 \uACB0\uC815\uC744 \uC900\uC218\uD558\uBA70 \uC778\uD130\uD398\uC774\uC2A4\xB7\uC5D0\uB7EC \uCC98\uB9AC\uB97C \uC77C\uAD00\uB418\uAC8C \uAD6C\uD604\uD558\uB294\uAC00",
185054
+ passCriteria: "\uAC01 DD \uD2F0\uCF13\uC758 description\uC5D0 (a) \uCDA9\uC871\uD558\uB294 Architecture \uCEF4\uD3EC\uB10C\uD2B8/\uC778\uD130\uD398\uC774\uC2A4 (b) Implements \uB9C1\uD06C \u2192 Architecture (c) \uC778\uD130\uD398\uC774\uC2A4 \uC2DC\uADF8\uB2C8\uCC98 \uBCC0\uD615 \uC5C6\uC74C",
185055
+ severity: "major",
185056
+ evidence: {
185057
+ tools: ["jira_get_issue", "jira_get_links"]
185058
+ }
185059
+ }
185060
+ ]
184940
185061
  }
184941
185062
  };
184942
185063
 
184943
185064
  // src/tools/expert.ts
184944
185065
  var phaseSchema = external_exports.enum(["design", "implementation", "verification", "postmarket"]);
185066
+ var swScopeSchema = external_exports.enum(["sad", "soup", "dd"]);
184945
185067
  function buildChecklistText(roleKey, phase) {
184946
185068
  const cl = EXPERT_CHECKLISTS[roleKey];
184947
185069
  if (!cl) return `\uC54C \uC218 \uC5C6\uB294 \uC5ED\uD560: ${roleKey}`;
@@ -184953,6 +185075,21 @@ phase='${phase}'\uC5D0 \uD574\uB2F9 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.
184953
185075
  }
184954
185076
  return JSON.stringify({ role: cl.role, title: cl.title, items }, null, 2);
184955
185077
  }
185078
+ function buildSwArchitectChecklist(scope) {
185079
+ const cl = EXPERT_CHECKLISTS["sw-architect"];
185080
+ if (!cl) return `\uC54C \uC218 \uC5C6\uB294 \uC5ED\uD560: sw-architect`;
185081
+ const items = scope ? cl.items.filter((i2) => i2.scope?.includes(scope)) : cl.items;
185082
+ const base = JSON.stringify({ role: cl.role, title: cl.title, scope, items }, null, 2);
185083
+ if (!scope) {
185084
+ return base + "\n\n> \u26A0\uFE0F scope \uBBF8\uC9C0\uC815 \u2014 8\uAC1C \uC804\uCCB4 \uD3C9\uAC00. EA \uB77C\uC774\uD504\uC0AC\uC774\uD074 \uC2DC\uC810\uC774 \uB2E4\uB974\uBA74 \uC801\uC808\uD55C scope(sad | soup | dd) \uAD8C\uC7A5.\n";
185085
+ }
185086
+ if (items.length === 0) {
185087
+ return `${cl.title}
185088
+
185089
+ scope='${scope}'\uC5D0 \uD574\uB2F9 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. (\uC798\uBABB\uB41C scope \uAC12 \uAC00\uB2A5)`;
185090
+ }
185091
+ return base;
185092
+ }
184956
185093
  var registerExpertTools = (ctx2) => {
184957
185094
  ctx2.server.tool(
184958
185095
  "expert_get_regulatory_checklist",
@@ -184972,6 +185109,14 @@ var registerExpertTools = (ctx2) => {
184972
185109
  ]
184973
185110
  })
184974
185111
  );
185112
+ ctx2.server.tool(
185113
+ "expert_get_sw_architect_checklist",
185114
+ "[\uC804\uBB38\uAC00\xB7SW \uC544\uD0A4\uD14D\uCC98] SW Architect \uAC80\uC0AC \uCCB4\uD06C\uB9AC\uC2A4\uD2B8 \uBC18\uD658. (IEC 62304 \xA75\xB7IEC 42010\xB7SOUP \uC120\uC815) scope: sad|soup|dd (\uBBF8\uC9C0\uC815 \uC2DC \uC804\uCCB4 \u2014 \uC7A1\uC74C \uACBD\uACE0 \uD45C\uC2DC)",
185115
+ { scope: swScopeSchema.optional() },
185116
+ async ({ scope }) => ({
185117
+ content: [{ type: "text", text: buildSwArchitectChecklist(scope) }]
185118
+ })
185119
+ );
184975
185120
  };
184976
185121
 
184977
185122
  // src/tools/review-criteria.ts
@@ -185025,7 +185170,7 @@ var xrayClientSecret = process.env.XRAY_CLIENT_SECRET || "";
185025
185170
  var xray = xrayClientId && xrayClientSecret ? new XrayClient(xrayClientId, xrayClientSecret, jiraUrl, jiraEmail, jiraToken) : null;
185026
185171
  var server = new McpServer({
185027
185172
  name: "jira-confluence",
185028
- version: "0.1.25"
185173
+ version: "0.1.26"
185029
185174
  });
185030
185175
  var ctx = { server, jira, confluence, risk, xray };
185031
185176
  registerJiraCrudTools(ctx);