@neobiotechlabs/neobiotech-dev-agent 0.1.14 → 0.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from "node:module";
3
+ import { fileURLToPath as __f2p } from "node:url";
4
+ import { dirname as __dn } from "node:path";
3
5
  const require = createRequire(import.meta.url);
6
+ const __filename = __f2p(import.meta.url);
7
+ const __dirname = __dn(__filename);
4
8
  var __create = Object.create;
5
9
  var __defProp = Object.defineProperty;
6
10
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -3236,8 +3240,8 @@ var require_utils = __commonJS({
3236
3240
  }
3237
3241
  return ind;
3238
3242
  }
3239
- function removeDotSegments(path2) {
3240
- let input = path2;
3243
+ function removeDotSegments(path3) {
3244
+ let input = path3;
3241
3245
  const output = [];
3242
3246
  let nextSlash = -1;
3243
3247
  let len = 0;
@@ -3489,8 +3493,8 @@ var require_schemes = __commonJS({
3489
3493
  wsComponent.secure = void 0;
3490
3494
  }
3491
3495
  if (wsComponent.resourceName) {
3492
- const [path2, query] = wsComponent.resourceName.split("?");
3493
- wsComponent.path = path2 && path2 !== "/" ? path2 : void 0;
3496
+ const [path3, query] = wsComponent.resourceName.split("?");
3497
+ wsComponent.path = path3 && path3 !== "/" ? path3 : void 0;
3494
3498
  wsComponent.query = query;
3495
3499
  wsComponent.resourceName = void 0;
3496
3500
  }
@@ -14950,8 +14954,8 @@ var init_jira_client = __esm({
14950
14954
  "Authorization": this.authHeader
14951
14955
  };
14952
14956
  }
14953
- async request(path2, options = {}) {
14954
- const resp = await fetch(`${this.baseUrl}/rest/api/3${path2}`, {
14957
+ async request(path3, options = {}) {
14958
+ const resp = await fetch(`${this.baseUrl}/rest/api/3${path3}`, {
14955
14959
  method: options.method || "GET",
14956
14960
  headers: this.headers(),
14957
14961
  body: options.body ? JSON.stringify(options.body) : void 0
@@ -15441,25 +15445,25 @@ var require_utils2 = __commonJS({
15441
15445
  }
15442
15446
  mkdirSync2(folder);
15443
15447
  };
15444
- Utils.prototype.writeFileTo = function(path2, content, overwrite, attr) {
15448
+ Utils.prototype.writeFileTo = function(path3, content, overwrite, attr) {
15445
15449
  const self2 = this;
15446
- if (self2.fs.existsSync(path2)) {
15450
+ if (self2.fs.existsSync(path3)) {
15447
15451
  if (!overwrite) return false;
15448
- var stat2 = self2.fs.statSync(path2);
15452
+ var stat2 = self2.fs.statSync(path3);
15449
15453
  if (stat2.isDirectory()) {
15450
15454
  return false;
15451
15455
  }
15452
15456
  }
15453
- var folder = pth.dirname(path2);
15457
+ var folder = pth.dirname(path3);
15454
15458
  if (!self2.fs.existsSync(folder)) {
15455
15459
  self2.makeDir(folder);
15456
15460
  }
15457
15461
  var fd;
15458
15462
  try {
15459
- fd = self2.fs.openSync(path2, "w", 438);
15463
+ fd = self2.fs.openSync(path3, "w", 438);
15460
15464
  } catch (e2) {
15461
- self2.fs.chmodSync(path2, 438);
15462
- fd = self2.fs.openSync(path2, "w", 438);
15465
+ self2.fs.chmodSync(path3, 438);
15466
+ fd = self2.fs.openSync(path3, "w", 438);
15463
15467
  }
15464
15468
  if (fd) {
15465
15469
  try {
@@ -15468,31 +15472,31 @@ var require_utils2 = __commonJS({
15468
15472
  self2.fs.closeSync(fd);
15469
15473
  }
15470
15474
  }
15471
- self2.fs.chmodSync(path2, attr || 438);
15475
+ self2.fs.chmodSync(path3, attr || 438);
15472
15476
  return true;
15473
15477
  };
15474
- Utils.prototype.writeFileToAsync = function(path2, content, overwrite, attr, callback) {
15478
+ Utils.prototype.writeFileToAsync = function(path3, content, overwrite, attr, callback) {
15475
15479
  if (typeof attr === "function") {
15476
15480
  callback = attr;
15477
15481
  attr = void 0;
15478
15482
  }
15479
15483
  const self2 = this;
15480
- self2.fs.exists(path2, function(exist) {
15484
+ self2.fs.exists(path3, function(exist) {
15481
15485
  if (exist && !overwrite) return callback(false);
15482
- self2.fs.stat(path2, function(err, stat2) {
15486
+ self2.fs.stat(path3, function(err, stat2) {
15483
15487
  if (exist && stat2.isDirectory()) {
15484
15488
  return callback(false);
15485
15489
  }
15486
- var folder = pth.dirname(path2);
15490
+ var folder = pth.dirname(path3);
15487
15491
  self2.fs.exists(folder, function(exists) {
15488
15492
  if (!exists) self2.makeDir(folder);
15489
- self2.fs.open(path2, "w", 438, function(err2, fd) {
15493
+ self2.fs.open(path3, "w", 438, function(err2, fd) {
15490
15494
  if (err2) {
15491
- self2.fs.chmod(path2, 438, function() {
15492
- self2.fs.open(path2, "w", 438, function(err3, fd2) {
15495
+ self2.fs.chmod(path3, 438, function() {
15496
+ self2.fs.open(path3, "w", 438, function(err3, fd2) {
15493
15497
  self2.fs.write(fd2, content, 0, content.length, 0, function() {
15494
15498
  self2.fs.close(fd2, function() {
15495
- self2.fs.chmod(path2, attr || 438, function() {
15499
+ self2.fs.chmod(path3, attr || 438, function() {
15496
15500
  callback(true);
15497
15501
  });
15498
15502
  });
@@ -15502,13 +15506,13 @@ var require_utils2 = __commonJS({
15502
15506
  } else if (fd) {
15503
15507
  self2.fs.write(fd, content, 0, content.length, 0, function() {
15504
15508
  self2.fs.close(fd, function() {
15505
- self2.fs.chmod(path2, attr || 438, function() {
15509
+ self2.fs.chmod(path3, attr || 438, function() {
15506
15510
  callback(true);
15507
15511
  });
15508
15512
  });
15509
15513
  });
15510
15514
  } else {
15511
- self2.fs.chmod(path2, attr || 438, function() {
15515
+ self2.fs.chmod(path3, attr || 438, function() {
15512
15516
  callback(true);
15513
15517
  });
15514
15518
  }
@@ -15517,7 +15521,7 @@ var require_utils2 = __commonJS({
15517
15521
  });
15518
15522
  });
15519
15523
  };
15520
- Utils.prototype.findFiles = function(path2) {
15524
+ Utils.prototype.findFiles = function(path3) {
15521
15525
  const self2 = this;
15522
15526
  function findSync(dir, pattern2, recursive) {
15523
15527
  if (typeof pattern2 === "boolean") {
@@ -15526,16 +15530,16 @@ var require_utils2 = __commonJS({
15526
15530
  }
15527
15531
  let files = [];
15528
15532
  self2.fs.readdirSync(dir).forEach(function(file) {
15529
- const path3 = pth.join(dir, file);
15530
- const stat2 = self2.fs.statSync(path3);
15531
- if (!pattern2 || pattern2.test(path3)) {
15532
- files.push(pth.normalize(path3) + (stat2.isDirectory() ? self2.sep : ""));
15533
+ const path4 = pth.join(dir, file);
15534
+ const stat2 = self2.fs.statSync(path4);
15535
+ if (!pattern2 || pattern2.test(path4)) {
15536
+ files.push(pth.normalize(path4) + (stat2.isDirectory() ? self2.sep : ""));
15533
15537
  }
15534
- if (stat2.isDirectory() && recursive) files = files.concat(findSync(path3, pattern2, recursive));
15538
+ if (stat2.isDirectory() && recursive) files = files.concat(findSync(path4, pattern2, recursive));
15535
15539
  });
15536
15540
  return files;
15537
15541
  }
15538
- return findSync(path2, void 0, true);
15542
+ return findSync(path3, void 0, true);
15539
15543
  };
15540
15544
  Utils.prototype.findFilesAsync = function(dir, cb) {
15541
15545
  const self2 = this;
@@ -15590,14 +15594,14 @@ var require_utils2 = __commonJS({
15590
15594
  return "UNSUPPORTED (" + method + ")";
15591
15595
  }
15592
15596
  };
15593
- Utils.canonical = function(path2) {
15594
- if (!path2) return "";
15595
- const safeSuffix = pth.posix.normalize("/" + path2.split("\\").join("/"));
15597
+ Utils.canonical = function(path3) {
15598
+ if (!path3) return "";
15599
+ const safeSuffix = pth.posix.normalize("/" + path3.split("\\").join("/"));
15596
15600
  return pth.join(".", safeSuffix);
15597
15601
  };
15598
- Utils.zipnamefix = function(path2) {
15599
- if (!path2) return "";
15600
- const safeSuffix = pth.posix.normalize("/" + path2.split("\\").join("/"));
15602
+ Utils.zipnamefix = function(path3) {
15603
+ if (!path3) return "";
15604
+ const safeSuffix = pth.posix.normalize("/" + path3.split("\\").join("/"));
15601
15605
  return pth.posix.join(".", safeSuffix);
15602
15606
  };
15603
15607
  Utils.findLast = function(arr, callback) {
@@ -15614,9 +15618,9 @@ var require_utils2 = __commonJS({
15614
15618
  prefix = pth.resolve(pth.normalize(prefix));
15615
15619
  var parts = name.split("/");
15616
15620
  for (var i2 = 0, l3 = parts.length; i2 < l3; i2++) {
15617
- var path2 = pth.normalize(pth.join(prefix, parts.slice(i2, l3).join(pth.sep)));
15618
- if (path2 === prefix || path2.startsWith(prefix + pth.sep)) {
15619
- return path2;
15621
+ var path3 = pth.normalize(pth.join(prefix, parts.slice(i2, l3).join(pth.sep)));
15622
+ if (path3 === prefix || path3.startsWith(prefix + pth.sep)) {
15623
+ return path3;
15620
15624
  }
15621
15625
  }
15622
15626
  return pth.normalize(pth.join(prefix, pth.basename(name)));
@@ -15663,8 +15667,8 @@ var require_fattr = __commonJS({
15663
15667
  "node_modules/adm-zip/util/fattr.js"(exports, module) {
15664
15668
  "use strict";
15665
15669
  var pth = __require("path");
15666
- module.exports = function(path2, { fs: fs4 }) {
15667
- var _path = path2 || "", _obj = newAttr(), _stat = null;
15670
+ module.exports = function(path3, { fs: fs4 }) {
15671
+ var _path = path3 || "", _obj = newAttr(), _stat = null;
15668
15672
  function newAttr() {
15669
15673
  return {
15670
15674
  directory: false,
@@ -145766,8 +145770,8 @@ function getErrorMap() {
145766
145770
 
145767
145771
  // node_modules/zod/v3/helpers/parseUtil.js
145768
145772
  var makeIssue = (params) => {
145769
- const { data, path: path2, errorMaps, issueData } = params;
145770
- const fullPath = [...path2, ...issueData.path || []];
145773
+ const { data, path: path3, errorMaps, issueData } = params;
145774
+ const fullPath = [...path3, ...issueData.path || []];
145771
145775
  const fullIssue = {
145772
145776
  ...issueData,
145773
145777
  path: fullPath
@@ -145883,11 +145887,11 @@ var errorUtil;
145883
145887
 
145884
145888
  // node_modules/zod/v3/types.js
145885
145889
  var ParseInputLazyPath = class {
145886
- constructor(parent, value, path2, key) {
145890
+ constructor(parent, value, path3, key) {
145887
145891
  this._cachedPath = [];
145888
145892
  this.parent = parent;
145889
145893
  this.data = value;
145890
- this._path = path2;
145894
+ this._path = path3;
145891
145895
  this._key = key;
145892
145896
  }
145893
145897
  get path() {
@@ -149524,10 +149528,10 @@ function assignProp(target, prop, value) {
149524
149528
  configurable: true
149525
149529
  });
149526
149530
  }
149527
- function getElementAtPath(obj, path2) {
149528
- if (!path2)
149531
+ function getElementAtPath(obj, path3) {
149532
+ if (!path3)
149529
149533
  return obj;
149530
- return path2.reduce((acc, key) => acc?.[key], obj);
149534
+ return path3.reduce((acc, key) => acc?.[key], obj);
149531
149535
  }
149532
149536
  function promiseAllObject(promisesObj) {
149533
149537
  const keys = Object.keys(promisesObj);
@@ -149847,11 +149851,11 @@ function aborted(x3, startIndex = 0) {
149847
149851
  }
149848
149852
  return false;
149849
149853
  }
149850
- function prefixIssues(path2, issues) {
149854
+ function prefixIssues(path3, issues) {
149851
149855
  return issues.map((iss) => {
149852
149856
  var _a;
149853
149857
  (_a = iss).path ?? (_a.path = []);
149854
- iss.path.unshift(path2);
149858
+ iss.path.unshift(path3);
149855
149859
  return iss;
149856
149860
  });
149857
149861
  }
@@ -159935,6 +159939,7 @@ var registerJiraCrudTools = (ctx2) => {
159935
159939
 
159936
159940
  // src/tools/confluence.ts
159937
159941
  init_markdown();
159942
+ import { readFileSync } from "fs";
159938
159943
  var STORAGE_BODY_WARN_BYTES = 2 * 1024 * 1024;
159939
159944
  var registerConfluenceTools = (ctx2) => {
159940
159945
  const { server: server2, confluence: confluence2 } = ctx2;
@@ -159990,11 +159995,28 @@ var registerConfluenceTools = (ctx2) => {
159990
159995
  server2.tool("confluence_publish_doc", "Publish a markdown document as a Confluence page. Markdown is converted to native Confluence storage format (headings/lists/tables/inline marks + code fences \u2192 code macro; YAML frontmatter auto-stripped). Create a new page, or update an existing one when page_id is provided (version auto-incremented). Use to publish doc_render output to Confluence after human review.", {
159991
159996
  space_key: external_exports.string().describe("Confluence space key (e.g. PROJ). Required even in update mode (returned for reference)."),
159992
159997
  title: external_exports.string().describe("Page title"),
159993
- markdown: external_exports.string().describe("Document content in markdown. Headings (#), bullet/ordered lists, GFM tables, fenced code blocks, and inline marks (**bold**/*italic*/`code`) are supported."),
159998
+ markdown: external_exports.string().optional().describe("Document content in markdown (inline). markdown_file\uACFC \uB3D9\uC2DC \uC0AC\uC6A9 \uBD88\uAC00. Headings (#), bullet/ordered lists, GFM tables, fenced code blocks, and inline marks (**bold**/*italic*/`code`) are supported."),
159999
+ markdown_file: external_exports.string().optional().describe("\uB85C\uCEEC \uB9C8\uD06C\uB2E4\uC6B4 \uD30C\uC77C \uACBD\uB85C. \uD070 \uBB38\uC11C(25KB+)\uB294 \uBAA8\uB378 \uD234 \uD638\uCD9C \uCD9C\uB825 \uD55C\uACC4\uB85C inline markdown \uC778\uC790\uAC00 \uC798\uB9B4 \uC218 \uC788\uC5B4 \uD30C\uC77C \uC9C1\uC811 \uC77D\uAE30 \uAD8C\uC7A5. markdown\uACFC \uB3D9\uC2DC \uC0AC\uC6A9 \uBD88\uAC00."),
159994
160000
  parent_page_id: external_exports.string().optional().describe("Parent page ID \u2014 create mode only, nests the new page under this parent. Ignored in update mode."),
159995
160001
  page_id: external_exports.string().optional().describe("Existing page ID. When provided, the page is UPDATED (current version fetched then incremented). When omitted, a NEW page is created.")
159996
- }, async ({ space_key, title, markdown, parent_page_id, page_id }) => {
159997
- const body = markdownToStorageFormat(markdown);
160002
+ }, async ({ space_key, title, markdown, markdown_file, parent_page_id, page_id }) => {
160003
+ if (!markdown && !markdown_file) {
160004
+ throw new Error("Either markdown or markdown_file must be provided");
160005
+ }
160006
+ if (markdown && markdown_file) {
160007
+ throw new Error("Provide either markdown or markdown_file, not both");
160008
+ }
160009
+ let md;
160010
+ if (markdown_file) {
160011
+ try {
160012
+ md = readFileSync(markdown_file, "utf8");
160013
+ } catch (err) {
160014
+ throw new Error(`Failed to read markdown_file "${markdown_file}": ${err?.message ?? err}`);
160015
+ }
160016
+ } else {
160017
+ md = markdown;
160018
+ }
160019
+ const body = markdownToStorageFormat(md);
159998
160020
  const bodyBytes = Buffer.byteLength(body, "utf8");
159999
160021
  const warning = bodyBytes > STORAGE_BODY_WARN_BYTES ? `storage body is ${bodyBytes} bytes (> ${STORAGE_BODY_WARN_BYTES}). Confluence may reject or render slowly \u2014 consider splitting into child pages.` : void 0;
160000
160022
  if (warning) console.error(`[confluence_publish_doc] ${warning}`);
@@ -160022,6 +160044,8 @@ var registerConfluenceTools = (ctx2) => {
160022
160044
  space_key,
160023
160045
  version: result?.version?.number,
160024
160046
  url,
160047
+ input_chars: md.length,
160048
+ input_source: markdown_file ?? "inline",
160025
160049
  body_chars: body.length,
160026
160050
  body_bytes: bodyBytes,
160027
160051
  ...warning ? { warning } : {}
@@ -160729,6 +160753,12 @@ var TOOL_CATALOG = [
160729
160753
  name: "expert_get_cybersecurity_checklist",
160730
160754
  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",
160731
160755
  category: "MDR \uC804\uBB38\uAC00"
160756
+ },
160757
+ // 문서 리뷰 soft verdict 평가 기준 (layer ② 데이터)
160758
+ {
160759
+ name: "review_get_criteria",
160760
+ description: "[\uBB38\uC11C \uB9AC\uBDF0\xB7soft verdict] document-content-reviewer\xB7requirement-coverage-tracker \uD3C9\uAC00 \uAE30\uC900(\uB808\uC774\uC5B4 \u2461) \uBC18\uD658. generic \uAE30\uBCF8 \u2014 consumer cwd\uC758 data/review-criteria.md(\uC624\uBC84\uB77C\uC774\uB4DC)\uAC00 \uC788\uC73C\uBA74 subagent\uAC00 \uCD94\uAC00 Read\uB85C \uBCF4\uC644.",
160761
+ category: "\uBB38\uC11C \uB9AC\uBDF0"
160732
160762
  }
160733
160763
  ];
160734
160764
  var WORKFLOWS = {
@@ -161351,7 +161381,7 @@ var registerDocValidationTools = (ctx2) => {
161351
161381
  };
161352
161382
 
161353
161383
  // src/tools/init.ts
161354
- import { readFileSync, writeFileSync as writeFileSync2, existsSync } from "fs";
161384
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync } from "fs";
161355
161385
  import { join as join2 } from "path";
161356
161386
  var registerInitTools = ({ server: server2 }) => {
161357
161387
  server2.tool(
@@ -161367,7 +161397,7 @@ var registerInitTools = ({ server: server2 }) => {
161367
161397
  try {
161368
161398
  let content = "";
161369
161399
  if (existsSync(claudeMdPath)) {
161370
- content = readFileSync(claudeMdPath, "utf-8");
161400
+ content = readFileSync2(claudeMdPath, "utf-8");
161371
161401
  if (content.includes(line)) {
161372
161402
  return { content: [{ type: "text", text: `\uC774\uBBF8 CLAUDE.md\uC5D0 ${project_key} \uD504\uB85C\uC81D\uD2B8 \uC124\uC815\uC774 \uC788\uC2B5\uB2C8\uB2E4.` }] };
161373
161403
  }
@@ -161392,7 +161422,7 @@ var registerInitTools = ({ server: server2 }) => {
161392
161422
  };
161393
161423
 
161394
161424
  // src/tools/doc-render.ts
161395
- import { readFileSync as readFileSync2 } from "fs";
161425
+ import { readFileSync as readFileSync3 } from "fs";
161396
161426
  import { fileURLToPath } from "url";
161397
161427
  import path from "path";
161398
161428
 
@@ -161492,7 +161522,7 @@ var registerDocRenderTools = (ctx2) => {
161492
161522
  throw new Error(`template '${template}' (mode=${entry.mode}) \uB80C\uB354\uB294 \uC544\uC9C1 \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uD604\uC7AC freeform\uB9CC \uAD6C\uD604\uB428.`);
161493
161523
  }
161494
161524
  const templatePath = path.join(TEMPLATE_DIR, entry.path);
161495
- const templateBody = readFileSync2(templatePath, "utf8");
161525
+ const templateBody = readFileSync3(templatePath, "utf8");
161496
161526
  const date3 = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
161497
161527
  const { rendered, unresolved } = renderTemplate({
161498
161528
  template: templateBody,
@@ -161544,7 +161574,8 @@ var registerDocRenderTools = (ctx2) => {
161544
161574
  };
161545
161575
 
161546
161576
  // src/tools/jira-attach.ts
161547
- import { readFileSync as readFileSync4 } from "fs";
161577
+ import { readFileSync as readFileSync5 } from "fs";
161578
+ import { execFileSync } from "child_process";
161548
161579
 
161549
161580
  // src/utils/markdownToPdf.ts
161550
161581
  import { existsSync as existsSync2, writeFileSync as writeFileSync3 } from "fs";
@@ -172854,16 +172885,16 @@ var $f43aec954cdfdf21$export$2e2bcd8739ae039 = class _$f43aec954cdfdf21$export$2
172854
172885
  * @return {Path}
172855
172886
  */
172856
172887
  mapPoints(fn) {
172857
- let path2 = new _$f43aec954cdfdf21$export$2e2bcd8739ae039();
172888
+ let path3 = new _$f43aec954cdfdf21$export$2e2bcd8739ae039();
172858
172889
  for (let c of this.commands) {
172859
172890
  let args = [];
172860
172891
  for (let i2 = 0; i2 < c.args.length; i2 += 2) {
172861
172892
  let [x3, y2] = fn(c.args[i2], c.args[i2 + 1]);
172862
172893
  args.push(x3, y2);
172863
172894
  }
172864
- path2[c.command](...args);
172895
+ path3[c.command](...args);
172865
172896
  }
172866
- return path2;
172897
+ return path3;
172867
172898
  }
172868
172899
  /**
172869
172900
  * Transforms the path by the given matrix.
@@ -173556,7 +173587,7 @@ var $69aac16029968692$export$2e2bcd8739ae039 = class extends (0, $f92906be28e617
173556
173587
  // Converts contours to a Path object that can be rendered
173557
173588
  _getPath() {
173558
173589
  let contours = this._getContours();
173559
- let path2 = new (0, $f43aec954cdfdf21$export$2e2bcd8739ae039)();
173590
+ let path3 = new (0, $f43aec954cdfdf21$export$2e2bcd8739ae039)();
173560
173591
  for (let i2 = 0; i2 < contours.length; i2++) {
173561
173592
  let contour = contours[i2];
173562
173593
  let firstPt = contour[0];
@@ -173572,26 +173603,26 @@ var $69aac16029968692$export$2e2bcd8739ae039 = class extends (0, $f92906be28e617
173572
173603
  firstPt = new $69aac16029968692$export$baf26146a414f24a(false, false, (firstPt.x + lastPt.x) / 2, (firstPt.y + lastPt.y) / 2);
173573
173604
  var curvePt = firstPt;
173574
173605
  }
173575
- path2.moveTo(firstPt.x, firstPt.y);
173606
+ path3.moveTo(firstPt.x, firstPt.y);
173576
173607
  for (let j2 = start; j2 < contour.length; j2++) {
173577
173608
  let pt = contour[j2];
173578
173609
  let prevPt = j2 === 0 ? firstPt : contour[j2 - 1];
173579
- if (prevPt.onCurve && pt.onCurve) path2.lineTo(pt.x, pt.y);
173610
+ if (prevPt.onCurve && pt.onCurve) path3.lineTo(pt.x, pt.y);
173580
173611
  else if (prevPt.onCurve && !pt.onCurve) var curvePt = pt;
173581
173612
  else if (!prevPt.onCurve && !pt.onCurve) {
173582
173613
  let midX = (prevPt.x + pt.x) / 2;
173583
173614
  let midY = (prevPt.y + pt.y) / 2;
173584
- path2.quadraticCurveTo(prevPt.x, prevPt.y, midX, midY);
173615
+ path3.quadraticCurveTo(prevPt.x, prevPt.y, midX, midY);
173585
173616
  var curvePt = pt;
173586
173617
  } else if (!prevPt.onCurve && pt.onCurve) {
173587
- path2.quadraticCurveTo(curvePt.x, curvePt.y, pt.x, pt.y);
173618
+ path3.quadraticCurveTo(curvePt.x, curvePt.y, pt.x, pt.y);
173588
173619
  var curvePt = null;
173589
173620
  } else throw new Error("Unknown TTF path state");
173590
173621
  }
173591
- if (curvePt) path2.quadraticCurveTo(curvePt.x, curvePt.y, firstPt.x, firstPt.y);
173592
- path2.closePath();
173622
+ if (curvePt) path3.quadraticCurveTo(curvePt.x, curvePt.y, firstPt.x, firstPt.y);
173623
+ path3.closePath();
173593
173624
  }
173594
- return path2;
173625
+ return path3;
173595
173626
  }
173596
173627
  constructor(...args) {
173597
173628
  super(...args);
@@ -173614,7 +173645,7 @@ var $62cc5109c6101893$export$2e2bcd8739ae039 = class extends (0, $f92906be28e617
173614
173645
  let str = cff.topDict.CharStrings[this.id];
173615
173646
  let end = str.offset + str.length;
173616
173647
  stream2.pos = str.offset;
173617
- let path2 = new (0, $f43aec954cdfdf21$export$2e2bcd8739ae039)();
173648
+ let path3 = new (0, $f43aec954cdfdf21$export$2e2bcd8739ae039)();
173618
173649
  let stack = [];
173619
173650
  let trans = [];
173620
173651
  let width = null;
@@ -173642,8 +173673,8 @@ var $62cc5109c6101893$export$2e2bcd8739ae039 = class extends (0, $f92906be28e617
173642
173673
  return stack.length = 0;
173643
173674
  }
173644
173675
  function moveTo(x4, y3) {
173645
- if (open) path2.closePath();
173646
- path2.moveTo(x4, y3);
173676
+ if (open) path3.closePath();
173677
+ path3.moveTo(x4, y3);
173647
173678
  open = true;
173648
173679
  }
173649
173680
  let parse4 = function() {
@@ -173670,7 +173701,7 @@ var $62cc5109c6101893$export$2e2bcd8739ae039 = class extends (0, $f92906be28e617
173670
173701
  while (stack.length >= 2) {
173671
173702
  x3 += stack.shift();
173672
173703
  y2 += stack.shift();
173673
- path2.lineTo(x3, y2);
173704
+ path3.lineTo(x3, y2);
173674
173705
  }
173675
173706
  break;
173676
173707
  case 6:
@@ -173679,7 +173710,7 @@ var $62cc5109c6101893$export$2e2bcd8739ae039 = class extends (0, $f92906be28e617
173679
173710
  while (stack.length >= 1) {
173680
173711
  if (phase) x3 += stack.shift();
173681
173712
  else y2 += stack.shift();
173682
- path2.lineTo(x3, y2);
173713
+ path3.lineTo(x3, y2);
173683
173714
  phase = !phase;
173684
173715
  }
173685
173716
  break;
@@ -173691,7 +173722,7 @@ var $62cc5109c6101893$export$2e2bcd8739ae039 = class extends (0, $f92906be28e617
173691
173722
  c2y = c1y + stack.shift();
173692
173723
  x3 = c2x + stack.shift();
173693
173724
  y2 = c2y + stack.shift();
173694
- path2.bezierCurveTo(c1x, c1y, c2x, c2y, x3, y2);
173725
+ path3.bezierCurveTo(c1x, c1y, c2x, c2y, x3, y2);
173695
173726
  }
173696
173727
  break;
173697
173728
  case 10:
@@ -173715,7 +173746,7 @@ var $62cc5109c6101893$export$2e2bcd8739ae039 = class extends (0, $f92906be28e617
173715
173746
  if (cff.version >= 2) break;
173716
173747
  if (stack.length > 0) checkWidth();
173717
173748
  if (open) {
173718
- path2.closePath();
173749
+ path3.closePath();
173719
173750
  open = false;
173720
173751
  }
173721
173752
  break;
@@ -173763,17 +173794,17 @@ var $62cc5109c6101893$export$2e2bcd8739ae039 = class extends (0, $f92906be28e617
173763
173794
  c2y = c1y + stack.shift();
173764
173795
  x3 = c2x + stack.shift();
173765
173796
  y2 = c2y + stack.shift();
173766
- path2.bezierCurveTo(c1x, c1y, c2x, c2y, x3, y2);
173797
+ path3.bezierCurveTo(c1x, c1y, c2x, c2y, x3, y2);
173767
173798
  }
173768
173799
  x3 += stack.shift();
173769
173800
  y2 += stack.shift();
173770
- path2.lineTo(x3, y2);
173801
+ path3.lineTo(x3, y2);
173771
173802
  break;
173772
173803
  case 25:
173773
173804
  while (stack.length >= 8) {
173774
173805
  x3 += stack.shift();
173775
173806
  y2 += stack.shift();
173776
- path2.lineTo(x3, y2);
173807
+ path3.lineTo(x3, y2);
173777
173808
  }
173778
173809
  c1x = x3 + stack.shift();
173779
173810
  c1y = y2 + stack.shift();
@@ -173781,7 +173812,7 @@ var $62cc5109c6101893$export$2e2bcd8739ae039 = class extends (0, $f92906be28e617
173781
173812
  c2y = c1y + stack.shift();
173782
173813
  x3 = c2x + stack.shift();
173783
173814
  y2 = c2y + stack.shift();
173784
- path2.bezierCurveTo(c1x, c1y, c2x, c2y, x3, y2);
173815
+ path3.bezierCurveTo(c1x, c1y, c2x, c2y, x3, y2);
173785
173816
  break;
173786
173817
  case 26:
173787
173818
  if (stack.length % 2) x3 += stack.shift();
@@ -173792,7 +173823,7 @@ var $62cc5109c6101893$export$2e2bcd8739ae039 = class extends (0, $f92906be28e617
173792
173823
  c2y = c1y + stack.shift();
173793
173824
  x3 = c2x;
173794
173825
  y2 = c2y + stack.shift();
173795
- path2.bezierCurveTo(c1x, c1y, c2x, c2y, x3, y2);
173826
+ path3.bezierCurveTo(c1x, c1y, c2x, c2y, x3, y2);
173796
173827
  }
173797
173828
  break;
173798
173829
  case 27:
@@ -173804,7 +173835,7 @@ var $62cc5109c6101893$export$2e2bcd8739ae039 = class extends (0, $f92906be28e617
173804
173835
  c2y = c1y + stack.shift();
173805
173836
  x3 = c2x + stack.shift();
173806
173837
  y2 = c2y;
173807
- path2.bezierCurveTo(c1x, c1y, c2x, c2y, x3, y2);
173838
+ path3.bezierCurveTo(c1x, c1y, c2x, c2y, x3, y2);
173808
173839
  }
173809
173840
  break;
173810
173841
  case 28:
@@ -173843,7 +173874,7 @@ var $62cc5109c6101893$export$2e2bcd8739ae039 = class extends (0, $f92906be28e617
173843
173874
  x3 = c2x + stack.shift();
173844
173875
  y2 = c2y + (stack.length === 1 ? stack.shift() : 0);
173845
173876
  }
173846
- path2.bezierCurveTo(c1x, c1y, c2x, c2y, x3, y2);
173877
+ path3.bezierCurveTo(c1x, c1y, c2x, c2y, x3, y2);
173847
173878
  phase = !phase;
173848
173879
  }
173849
173880
  break;
@@ -173969,8 +174000,8 @@ var $62cc5109c6101893$export$2e2bcd8739ae039 = class extends (0, $f92906be28e617
173969
174000
  c6y = c5y;
173970
174001
  x3 = c6x;
173971
174002
  y2 = c6y;
173972
- path2.bezierCurveTo(c1x, c1y, c2x, c2y, c3x, c3y);
173973
- path2.bezierCurveTo(c4x, c4y, c5x, c5y, c6x, c6y);
174003
+ path3.bezierCurveTo(c1x, c1y, c2x, c2y, c3x, c3y);
174004
+ path3.bezierCurveTo(c4x, c4y, c5x, c5y, c6x, c6y);
173974
174005
  break;
173975
174006
  case 35:
173976
174007
  pts = [];
@@ -173979,8 +174010,8 @@ var $62cc5109c6101893$export$2e2bcd8739ae039 = class extends (0, $f92906be28e617
173979
174010
  y2 += stack.shift();
173980
174011
  pts.push(x3, y2);
173981
174012
  }
173982
- path2.bezierCurveTo(...pts.slice(0, 6));
173983
- path2.bezierCurveTo(...pts.slice(6));
174013
+ path3.bezierCurveTo(...pts.slice(0, 6));
174014
+ path3.bezierCurveTo(...pts.slice(6));
173984
174015
  stack.shift();
173985
174016
  break;
173986
174017
  case 36:
@@ -173998,8 +174029,8 @@ var $62cc5109c6101893$export$2e2bcd8739ae039 = class extends (0, $f92906be28e617
173998
174029
  c6y = c5y;
173999
174030
  x3 = c6x;
174000
174031
  y2 = c6y;
174001
- path2.bezierCurveTo(c1x, c1y, c2x, c2y, c3x, c3y);
174002
- path2.bezierCurveTo(c4x, c4y, c5x, c5y, c6x, c6y);
174032
+ path3.bezierCurveTo(c1x, c1y, c2x, c2y, c3x, c3y);
174033
+ path3.bezierCurveTo(c4x, c4y, c5x, c5y, c6x, c6y);
174003
174034
  break;
174004
174035
  case 37:
174005
174036
  let startx = x3;
@@ -174018,8 +174049,8 @@ var $62cc5109c6101893$export$2e2bcd8739ae039 = class extends (0, $f92906be28e617
174018
174049
  y2 += stack.shift();
174019
174050
  }
174020
174051
  pts.push(x3, y2);
174021
- path2.bezierCurveTo(...pts.slice(0, 6));
174022
- path2.bezierCurveTo(...pts.slice(6));
174052
+ path3.bezierCurveTo(...pts.slice(0, 6));
174053
+ path3.bezierCurveTo(...pts.slice(6));
174023
174054
  break;
174024
174055
  default:
174025
174056
  throw new Error(`Unknown op: 12 ${op}`);
@@ -174039,8 +174070,8 @@ var $62cc5109c6101893$export$2e2bcd8739ae039 = class extends (0, $f92906be28e617
174039
174070
  }
174040
174071
  };
174041
174072
  parse4();
174042
- if (open) path2.closePath();
174043
- return path2;
174073
+ if (open) path3.closePath();
174074
+ return path3;
174044
174075
  }
174045
174076
  constructor(...args) {
174046
174077
  super(...args);
@@ -174500,7 +174531,7 @@ var $807e58506be70005$var$Glyf = new Struct({
174500
174531
  yPoints: new ArrayT($807e58506be70005$var$Point, 0)
174501
174532
  });
174502
174533
  var $807e58506be70005$export$2e2bcd8739ae039 = class {
174503
- encodeSimple(path2, instructions = []) {
174534
+ encodeSimple(path3, instructions = []) {
174504
174535
  let endPtsOfContours = [];
174505
174536
  let xPoints = [];
174506
174537
  let yPoints = [];
@@ -174508,14 +174539,14 @@ var $807e58506be70005$export$2e2bcd8739ae039 = class {
174508
174539
  let same = 0;
174509
174540
  let lastX = 0, lastY = 0, lastFlag = 0;
174510
174541
  let pointCount = 0;
174511
- for (let i2 = 0; i2 < path2.commands.length; i2++) {
174512
- let c = path2.commands[i2];
174542
+ for (let i2 = 0; i2 < path3.commands.length; i2++) {
174543
+ let c = path3.commands[i2];
174513
174544
  for (let j2 = 0; j2 < c.args.length; j2 += 2) {
174514
174545
  let x3 = c.args[j2];
174515
174546
  let y2 = c.args[j2 + 1];
174516
174547
  let flag = 0;
174517
174548
  if (c.command === "quadraticCurveTo" && j2 === 2) {
174518
- let next = path2.commands[i2 + 1];
174549
+ let next = path3.commands[i2 + 1];
174519
174550
  if (next && next.command === "quadraticCurveTo") {
174520
174551
  let midX = (lastX + next.args[0]) / 2;
174521
174552
  let midY = (lastY + next.args[1]) / 2;
@@ -174542,8 +174573,8 @@ var $807e58506be70005$export$2e2bcd8739ae039 = class {
174542
174573
  }
174543
174574
  if (c.command === "closePath") endPtsOfContours.push(pointCount - 1);
174544
174575
  }
174545
- if (path2.commands.length > 1 && path2.commands[path2.commands.length - 1].command !== "closePath") endPtsOfContours.push(pointCount - 1);
174546
- let bbox = path2.bbox;
174576
+ if (path3.commands.length > 1 && path3.commands[path3.commands.length - 1].command !== "closePath") endPtsOfContours.push(pointCount - 1);
174577
+ let bbox = path3.bbox;
174547
174578
  let glyf = {
174548
174579
  numberOfContours: endPtsOfContours.length,
174549
174580
  xMin: bbox.minX,
@@ -174650,7 +174681,7 @@ var $001d739428a71d5a$export$2e2bcd8739ae039 = class extends (0, $5cc7476da92df3
174650
174681
  for (let gid of this.glyphs) {
174651
174682
  this.charstrings.push(this.cff.getCharString(gid));
174652
174683
  let glyph = this.font.getGlyph(gid);
174653
- let path2 = glyph.path;
174684
+ let path3 = glyph.path;
174654
174685
  for (let subr in glyph._usedGsubrs) gsubrs[subr] = true;
174655
174686
  }
174656
174687
  this.gsubrs = this.subsetSubrs(this.cff.globalSubrIndex, gsubrs);
@@ -174688,7 +174719,7 @@ var $001d739428a71d5a$export$2e2bcd8739ae039 = class extends (0, $5cc7476da92df3
174688
174719
  used_fds[fd] = true;
174689
174720
  topDict.FDSelect.fds.push(fd_select[fd]);
174690
174721
  let glyph = this.font.getGlyph(gid);
174691
- let path2 = glyph.path;
174722
+ let path3 = glyph.path;
174692
174723
  for (let subr in glyph._usedSubrs) used_subrs[fd_select[fd]][subr] = true;
174693
174724
  }
174694
174725
  for (let i2 = 0; i2 < topDict.FDArray.length; i2++) {
@@ -174705,7 +174736,7 @@ var $001d739428a71d5a$export$2e2bcd8739ae039 = class extends (0, $5cc7476da92df3
174705
174736
  let used_subrs = {};
174706
174737
  for (let gid of this.glyphs) {
174707
174738
  let glyph = this.font.getGlyph(gid);
174708
- let path2 = glyph.path;
174739
+ let path3 = glyph.path;
174709
174740
  for (let subr in glyph._usedSubrs) used_subrs[subr] = true;
174710
174741
  }
174711
174742
  let privateDict = Object.assign({}, this.cff.topDict.Private);
@@ -177013,17 +177044,17 @@ $557adaaeb0c7885f$exports = $557adaaeb0c7885f$var$LineBreaker;
177013
177044
  import fs2 from "fs";
177014
177045
  import zlib2 from "zlib";
177015
177046
  var PNG = class _PNG {
177016
- static decode(path2, fn) {
177047
+ static decode(path3, fn) {
177017
177048
  {
177018
- return fs2.readFile(path2, function(err, file) {
177049
+ return fs2.readFile(path3, function(err, file) {
177019
177050
  const png = new _PNG(file);
177020
177051
  return png.decode((pixels) => fn(pixels));
177021
177052
  });
177022
177053
  }
177023
177054
  }
177024
- static load(path2) {
177055
+ static load(path3) {
177025
177056
  {
177026
- const file = fs2.readFileSync(path2);
177057
+ const file = fs2.readFileSync(path3);
177027
177058
  return new _PNG(file);
177028
177059
  }
177029
177060
  }
@@ -178891,15 +178922,15 @@ var readNumber = function(string3, cursor) {
178891
178922
  }
178892
178923
  return [i2 - 1, number4];
178893
178924
  };
178894
- var parse3 = function(path2) {
178925
+ var parse3 = function(path3) {
178895
178926
  const pathData = [];
178896
178927
  let command = null;
178897
178928
  let args = [];
178898
178929
  let argsCount = 0;
178899
178930
  let canHaveComma = false;
178900
178931
  let hadComma = false;
178901
- for (let i2 = 0; i2 < path2.length; i2 += 1) {
178902
- const c = path2.charAt(i2);
178932
+ for (let i2 = 0; i2 < path3.length; i2 += 1) {
178933
+ const c = path3.charAt(i2);
178903
178934
  if (isWsp(c)) {
178904
178935
  continue;
178905
178936
  }
@@ -178944,11 +178975,11 @@ var parse3 = function(path2) {
178944
178975
  const position = args.length;
178945
178976
  if (position === 0 || position === 1) {
178946
178977
  if (c !== "+" && c !== "-") {
178947
- [newCursor, number4] = readNumber(path2, i2);
178978
+ [newCursor, number4] = readNumber(path3, i2);
178948
178979
  }
178949
178980
  }
178950
178981
  if (position === 2 || position === 5 || position === 6) {
178951
- [newCursor, number4] = readNumber(path2, i2);
178982
+ [newCursor, number4] = readNumber(path3, i2);
178952
178983
  }
178953
178984
  if (position === 3 || position === 4) {
178954
178985
  if (c === "0") {
@@ -178959,7 +178990,7 @@ var parse3 = function(path2) {
178959
178990
  }
178960
178991
  }
178961
178992
  } else {
178962
- [newCursor, number4] = readNumber(path2, i2);
178993
+ [newCursor, number4] = readNumber(path3, i2);
178963
178994
  }
178964
178995
  if (number4 == null) {
178965
178996
  return pathData;
@@ -179215,8 +179246,8 @@ var segmentToBezier = function(cx2, cy2, th0, th1, rx, ry, sin_th, cos_th) {
179215
179246
  return [a00 * x1 + a01 * y1, a10 * x1 + a11 * y1, a00 * x22 + a01 * y2, a10 * x22 + a11 * y2, a00 * x3 + a01 * y3, a10 * x3 + a11 * y3];
179216
179247
  };
179217
179248
  var SVGPath = class {
179218
- static apply(doc, path2) {
179219
- const commands = parse3(path2);
179249
+ static apply(doc, path3) {
179250
+ const commands = parse3(path3);
179220
179251
  apply(commands, doc);
179221
179252
  }
179222
179253
  };
@@ -179401,8 +179432,8 @@ var VectorMixin = {
179401
179432
  }
179402
179433
  return this.closePath();
179403
179434
  },
179404
- path(path2) {
179405
- SVGPath.apply(this, path2);
179435
+ path(path3) {
179436
+ SVGPath.apply(this, path3);
179406
179437
  return this;
179407
179438
  },
179408
179439
  _windingRule(rule) {
@@ -184120,22 +184151,51 @@ function renderHr(doc) {
184120
184151
  doc.y = y2 + SPACE2.HR_AFTER;
184121
184152
  }
184122
184153
  function writePdfToTempFile(buffer) {
184123
- const path2 = join3(tmpdir(), `${randomUUID()}.pdf`);
184124
- writeFileSync3(path2, buffer);
184125
- return path2;
184154
+ const path3 = join3(tmpdir(), `${randomUUID()}.pdf`);
184155
+ writeFileSync3(path3, buffer);
184156
+ return path3;
184126
184157
  }
184127
184158
 
184128
184159
  // src/tools/jira-attach.ts
184129
184160
  var ATTACH_WARN_BYTES = 50 * 1024 * 1024;
184130
184161
  var ATTACH_HARD_LIMIT_BYTES = 100 * 1024 * 1024;
184131
184162
  var DEFAULT_PDF_FILENAME = "document.pdf";
184163
+ async function postAttachMetaComment(jira2, issueKey, filePath, filename) {
184164
+ if (!filePath) return { posted: false };
184165
+ let shortSha;
184166
+ try {
184167
+ shortSha = execFileSync("git", ["rev-parse", "--short", "HEAD"], {
184168
+ stdio: ["ignore", "pipe", "ignore"],
184169
+ encoding: "utf8",
184170
+ timeout: 3e3
184171
+ }).trim();
184172
+ } catch (err) {
184173
+ console.error(`[attach-meta] git hash \uCD94\uCD9C \uC2E4\uD328 (\uCF54\uBA58\uD2B8 \uC0DD\uB7B5): ${err?.message ?? err}`);
184174
+ return { posted: false };
184175
+ }
184176
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
184177
+ const body = `\u{1F4CE} \uCCA8\uBD80 \uBA54\uD0C0
184178
+
184179
+ - file: \`${filename}\`
184180
+ - local path: \`${filePath}\`
184181
+ - git: \`${shortSha}\` (${today})`;
184182
+ try {
184183
+ const comment = await jira2.addComment(issueKey, body);
184184
+ return { posted: true, commentId: String(comment?.id ?? "") };
184185
+ } catch (err) {
184186
+ const msg = `\uCCA8\uBD80 \uBA54\uD0C0 \uCF54\uBA58\uD2B8 \uAC8C\uC2DC \uC2E4\uD328 (\uCCA8\uBD80 \uC790\uCCB4\uB294 \uC131\uACF5): ${err?.message ?? err}`;
184187
+ console.error(`[attach-meta] ${msg}`);
184188
+ return { posted: false, warning: msg };
184189
+ }
184190
+ }
184132
184191
  var registerJiraAttachTools = (ctx2) => {
184133
184192
  const { server: server2, jira: jira2 } = ctx2;
184134
184193
  server2.tool(
184135
184194
  "markdown_to_pdf",
184136
184195
  "\uB9C8\uD06C\uB2E4\uC6B4\uC744 PDF\uB85C \uBCC0\uD658 (\uC2DC\uC2A4\uD15C \uD3F0\uD2B8 \uC790\uB3D9 \uAC10\uC9C0, \uD45C\uC9C0/\uBA38\uB9AC\uB9D0\xB7\uAF2C\uB9AC\uB9D0 \uC635\uC158). Jira \uCCA8\uBD80 \uC5C6\uC774 PDF \uACB0\uACFC\uB9CC \uBC18\uD658.",
184137
184196
  {
184138
- markdown: external_exports.string().describe("PDF\uB85C \uBCC0\uD658\uD560 \uB9C8\uD06C\uB2E4\uC6B4 \uBCF8\uBB38"),
184197
+ markdown: external_exports.string().optional().describe("PDF\uB85C \uBCC0\uD658\uD560 \uB9C8\uD06C\uB2E4\uC6B4 \uBCF8\uBB38 (inline). markdown_file\uACFC \uB3D9\uC2DC \uC0AC\uC6A9 \uBD88\uAC00."),
184198
+ markdown_file: external_exports.string().optional().describe("\uB85C\uCEEC \uB9C8\uD06C\uB2E4\uC6B4 \uD30C\uC77C \uACBD\uB85C. \uD070 \uBB38\uC11C(25KB+)\uB294 \uBAA8\uB378 \uD234 \uD638\uCD9C \uCD9C\uB825 \uD55C\uACC4\uB85C inline markdown \uC778\uC790\uAC00 \uC798\uB9B4 \uC218 \uC788\uC5B4 \uD30C\uC77C \uC9C1\uC811 \uC77D\uAE30 \uAD8C\uC7A5. markdown\uACFC \uB3D9\uC2DC \uC0AC\uC6A9 \uBD88\uAC00."),
184139
184199
  title: external_exports.string().optional().describe('\uBA38\uB9AC\uB9D0\xB7\uD45C\uC9C0\uC5D0 \uD45C\uC2DC\uD560 \uC81C\uBAA9 (\uAE30\uBCF8: source_ref \uB610\uB294 "Document")'),
184140
184200
  source_ref: external_exports.string().optional().describe('\uAF2C\uB9AC\uB9D0\xB7\uD45C\uC9C0 \uD478\uD130\uC5D0 \uD45C\uC2DC\uD560 \uCD9C\uCC98 (\uC608: "DYN-100 \xB7 2026-07-14")'),
184141
184201
  include_cover: external_exports.boolean().optional().default(false).describe("\uD45C\uC9C0 \uD398\uC774\uC9C0 \uD3EC\uD568 \uC5EC\uBD80 (\uAE30\uBCF8 false)"),
@@ -184145,8 +184205,24 @@ var registerJiraAttachTools = (ctx2) => {
184145
184205
  page_size: external_exports.enum(["A4", "LETTER", "LEGAL"]).optional().default("A4").describe("\uD398\uC774\uC9C0 \uD06C\uAE30"),
184146
184206
  output_mode: external_exports.enum(["base64", "tmpfile"]).optional().default("base64").describe("base64(\uAE30\uBCF8, JSON \uC548\uC804) / tmpfile(\uC808\uB300\uACBD\uB85C \uBC18\uD658, consumer\uAC00 unlink \uCC45\uC784)")
184147
184207
  },
184148
- async ({ markdown, title, source_ref, include_cover, author, font_path, font_family_name, page_size, output_mode }) => {
184149
- const result = await markdownToPdf(markdown, {
184208
+ async ({ markdown, markdown_file, title, source_ref, include_cover, author, font_path, font_family_name, page_size, output_mode }) => {
184209
+ if (!markdown && !markdown_file) {
184210
+ throw new Error("Either markdown or markdown_file must be provided");
184211
+ }
184212
+ if (markdown && markdown_file) {
184213
+ throw new Error("Provide either markdown or markdown_file, not both");
184214
+ }
184215
+ let md;
184216
+ if (markdown_file) {
184217
+ try {
184218
+ md = readFileSync5(markdown_file, "utf8");
184219
+ } catch (err) {
184220
+ throw new Error(`Failed to read markdown_file "${markdown_file}": ${err?.message ?? err}`);
184221
+ }
184222
+ } else {
184223
+ md = markdown;
184224
+ }
184225
+ const result = await markdownToPdf(md, {
184150
184226
  ...title !== void 0 ? { title } : {},
184151
184227
  ...source_ref !== void 0 ? { sourceRef: source_ref } : {},
184152
184228
  includeCover: include_cover,
@@ -184158,9 +184234,9 @@ var registerJiraAttachTools = (ctx2) => {
184158
184234
  });
184159
184235
  const buffer = result.buffer;
184160
184236
  if (output_mode === "tmpfile") {
184161
- const path2 = writePdfToTempFile(buffer);
184237
+ const path3 = writePdfToTempFile(buffer);
184162
184238
  const payload2 = {
184163
- path: path2,
184239
+ path: path3,
184164
184240
  bytes: buffer.length,
184165
184241
  encoding: "utf8"
184166
184242
  };
@@ -184197,7 +184273,7 @@ var registerJiraAttachTools = (ctx2) => {
184197
184273
  let buffer;
184198
184274
  if (file_path) {
184199
184275
  try {
184200
- buffer = readFileSync4(file_path);
184276
+ buffer = readFileSync5(file_path);
184201
184277
  } catch (err) {
184202
184278
  throw new Error(`Failed to read file_path "${file_path}": ${err?.message ?? err}`);
184203
184279
  }
@@ -184217,12 +184293,16 @@ var registerJiraAttachTools = (ctx2) => {
184217
184293
  console.error(`[jira_attach_file] ${warning}`);
184218
184294
  }
184219
184295
  const attachments = await jira2.addAttachment(issue_key, filename, buffer, mime_type);
184296
+ const meta = await postAttachMetaComment(jira2, issue_key, file_path, filename);
184220
184297
  const payload = {
184221
184298
  issue_key,
184222
184299
  filename,
184223
184300
  size_bytes: buffer.length,
184224
184301
  mime_type,
184225
- attachments
184302
+ attachments,
184303
+ comment_posted: meta.posted,
184304
+ ...meta.commentId ? { comment_id: meta.commentId } : {},
184305
+ ...meta.warning ? { comment_warning: meta.warning } : {}
184226
184306
  };
184227
184307
  if (warning) payload.warning = warning;
184228
184308
  return { content: [{ type: "text", text: JSON.stringify(payload, null, 2) }] };
@@ -184233,7 +184313,8 @@ var registerJiraAttachTools = (ctx2) => {
184233
184313
  "\uB9C8\uD06C\uB2E4\uC6B4 \u2192 PDF \uBCC0\uD658 \u2192 Jira \uCCA8\uBD80 \uC6D0\uC0F7. description\uC740 \uC218\uC815\uD558\uC9C0 \uC54A\uC73C\uBA70, summary \uC635\uC158\uC774 \uC788\uC73C\uBA74 \uCF54\uBA58\uD2B8\uB85C \uAC8C\uC2DC.",
184234
184314
  {
184235
184315
  issue_key: external_exports.string().describe("Jira \uC774\uC288 \uD0A4 (\uC608: DYN-100)"),
184236
- markdown: external_exports.string().describe("PDF\uB85C \uBCC0\uD658\uD560 \uB9C8\uD06C\uB2E4\uC6B4 \uBCF8\uBB38"),
184316
+ markdown: external_exports.string().optional().describe("PDF\uB85C \uBCC0\uD658\uD560 \uB9C8\uD06C\uB2E4\uC6B4 \uBCF8\uBB38 (inline). markdown_file\uACFC \uB3D9\uC2DC \uC0AC\uC6A9 \uBD88\uAC00."),
184317
+ markdown_file: external_exports.string().optional().describe("\uB85C\uCEEC \uB9C8\uD06C\uB2E4\uC6B4 \uD30C\uC77C \uACBD\uB85C. \uD070 \uBB38\uC11C(25KB+)\uB294 \uBAA8\uB378 \uD234 \uD638\uCD9C \uCD9C\uB825 \uD55C\uACC4\uB85C inline markdown \uC778\uC790\uAC00 \uC798\uB9B4 \uC218 \uC788\uC5B4 \uD30C\uC77C \uC9C1\uC811 \uC77D\uAE30 \uAD8C\uC7A5. markdown\uACFC \uB3D9\uC2DC \uC0AC\uC6A9 \uBD88\uAC00."),
184237
184318
  filename: external_exports.string().optional().default(DEFAULT_PDF_FILENAME).describe('\uCCA8\uBD80 \uD30C\uC77C\uBA85 (\uAE30\uBCF8 "document.pdf")'),
184238
184319
  summary: external_exports.string().optional().describe("\uCF54\uBA58\uD2B8\uB85C \uAC8C\uC2DC\uD560 \uC694\uC57D (Markdown ADF \uBCC0\uD658, description\uC740 \uBBF8\uC218\uC815)"),
184239
184320
  // pdfkit 옵션 위임 — title/source_ref/include_cover/author/font_path/font_family_name/page_size
@@ -184248,6 +184329,7 @@ var registerJiraAttachTools = (ctx2) => {
184248
184329
  async ({
184249
184330
  issue_key,
184250
184331
  markdown,
184332
+ markdown_file,
184251
184333
  filename,
184252
184334
  summary,
184253
184335
  title,
@@ -184258,7 +184340,23 @@ var registerJiraAttachTools = (ctx2) => {
184258
184340
  font_family_name,
184259
184341
  page_size
184260
184342
  }) => {
184261
- const result = await markdownToPdf(markdown, {
184343
+ if (!markdown && !markdown_file) {
184344
+ throw new Error("Either markdown or markdown_file must be provided");
184345
+ }
184346
+ if (markdown && markdown_file) {
184347
+ throw new Error("Provide either markdown or markdown_file, not both");
184348
+ }
184349
+ let md;
184350
+ if (markdown_file) {
184351
+ try {
184352
+ md = readFileSync5(markdown_file, "utf8");
184353
+ } catch (err) {
184354
+ throw new Error(`Failed to read markdown_file "${markdown_file}": ${err?.message ?? err}`);
184355
+ }
184356
+ } else {
184357
+ md = markdown;
184358
+ }
184359
+ const result = await markdownToPdf(md, {
184262
184360
  ...title !== void 0 ? { title } : {},
184263
184361
  ...source_ref !== void 0 ? { sourceRef: source_ref } : {},
184264
184362
  includeCover: include_cover,
@@ -184542,6 +184640,40 @@ var registerExpertTools = (ctx2) => {
184542
184640
  );
184543
184641
  };
184544
184642
 
184643
+ // src/tools/review-criteria.ts
184644
+ import { readFileSync as readFileSync6 } from "fs";
184645
+ import { fileURLToPath as fileURLToPath2 } from "url";
184646
+ import path2 from "path";
184647
+ var __dirname3 = path2.dirname(fileURLToPath2(import.meta.url));
184648
+ var CRITERIA_PATH = path2.resolve(__dirname3, "../data/review-criteria.md");
184649
+ var registerReviewCriteriaTools = (ctx2) => {
184650
+ ctx2.server.tool(
184651
+ "review_get_criteria",
184652
+ "[\uBB38\uC11C \uB9AC\uBDF0\xB7soft verdict] document-content-reviewer\xB7requirement-coverage-tracker\uC758 \uD3C9\uAC00 \uAE30\uC900(\uB808\uC774\uC5B4 \u2461) \uBC18\uD658. \uC758\uB8CC\uAE30\uAE30 \uD45C\uC900 \uAE30\uBC18 generic \uAE30\uBCF8 \u2014 consumer cwd\uC758 data/review-criteria.md(\uD504\uB85C\uC81D\uD2B8 \uC624\uBC84\uB77C\uC774\uB4DC)\uAC00 \uBCC4\uB3C4 \uC874\uC7AC\uD558\uBA74 subagent\uAC00 \uADF8\uAC83\uC744 \uCD94\uAC00 Read\uB85C \uBCF4\uC644. \uB9E4 \uD638\uCD9C \uC2DC \uB514\uC2A4\uD06C\uC5D0\uC11C \uC77D\uC74C(watch rebuild/installPath \uAC31\uC2E0 \uBC18\uC601).",
184653
+ {},
184654
+ async () => {
184655
+ let body;
184656
+ try {
184657
+ body = readFileSync6(CRITERIA_PATH, "utf8");
184658
+ } catch (err) {
184659
+ body = [
184660
+ "# Review Criteria \u2014 \uB85C\uB4DC \uC2E4\uD328",
184661
+ "",
184662
+ `\uACBD\uB85C: ${CRITERIA_PATH}`,
184663
+ `\uC624\uB958: ${err?.message ?? err}`,
184664
+ "",
184665
+ "plugin \uBC88\uB4E4\uC5D0 data/review-criteria.md\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
184666
+ '- package.json files \uBC30\uC5F4\uC5D0 "data" \uD3EC\uD568 \uC5EC\uBD80 \uD655\uC778.',
184667
+ "- installPath(dist/index.js \uC606)\uC5D0 data/ \uB514\uB809\uD130\uB9AC \uC874\uC7AC \uC5EC\uBD80 \uD655\uC778.",
184668
+ "",
184669
+ "\uD3C9\uAC00\uB294 \uACC4\uC18D \uAC00\uB2A5\uD558\uB098 generic \uAE30\uC900 \uC5C6\uC774 subagent\uC758 \uC77C\uBC18\uC801 LLM \uD3C9\uAC00\uB85C\uB9CC \uC9C4\uD589\uB429\uB2C8\uB2E4. findings\uC758 \uC2E0\uB8B0\uB3C4\uAC00 \uB0AE\uC544\uC9C8 \uC218 \uC788\uC2B5\uB2C8\uB2E4."
184670
+ ].join("\n");
184671
+ }
184672
+ return { content: [{ type: "text", text: body }] };
184673
+ }
184674
+ );
184675
+ };
184676
+
184545
184677
  // src/index.ts
184546
184678
  var jiraUrl = process.env.JIRA_URL || "";
184547
184679
  var jiraEmail = process.env.JIRA_EMAIL || "";
@@ -184559,7 +184691,7 @@ var xrayClientSecret = process.env.XRAY_CLIENT_SECRET || "";
184559
184691
  var xray = xrayClientId && xrayClientSecret ? new XrayClient(xrayClientId, xrayClientSecret, jiraUrl, jiraEmail, jiraToken) : null;
184560
184692
  var server = new McpServer({
184561
184693
  name: "jira-confluence",
184562
- version: "0.1.14"
184694
+ version: "0.1.16"
184563
184695
  });
184564
184696
  var ctx = { server, jira, confluence, risk, xray };
184565
184697
  registerJiraCrudTools(ctx);
@@ -184576,6 +184708,7 @@ registerInitTools(ctx);
184576
184708
  registerDocRenderTools(ctx);
184577
184709
  registerJiraAttachTools(ctx);
184578
184710
  registerExpertTools(ctx);
184711
+ registerReviewCriteriaTools(ctx);
184579
184712
  var transport = new StdioServerTransport();
184580
184713
  server.connect(transport).catch((err) => {
184581
184714
  console.error("Failed to start MCP server:", err);