@vibecodetown/mcp-server 2.2.0 → 2.2.1

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 (70) hide show
  1. package/README.md +10 -10
  2. package/build/auth/index.js +0 -2
  3. package/build/auth/public_key.js +6 -4
  4. package/build/bootstrap/doctor.js +113 -5
  5. package/build/bootstrap/installer.js +85 -15
  6. package/build/bootstrap/registry.js +11 -6
  7. package/build/bootstrap/skills-installer.js +365 -0
  8. package/build/dx/activity.js +26 -3
  9. package/build/engine.js +151 -0
  10. package/build/errors.js +107 -0
  11. package/build/generated/bridge_build_seed_input.js +2 -0
  12. package/build/generated/bridge_build_seed_output.js +2 -0
  13. package/build/generated/bridge_confirm_reference_input.js +2 -0
  14. package/build/generated/bridge_confirm_reference_output.js +2 -0
  15. package/build/generated/bridge_confirmed_reference_file.js +2 -0
  16. package/build/generated/bridge_generate_references_input.js +2 -0
  17. package/build/generated/bridge_generate_references_output.js +2 -0
  18. package/build/generated/bridge_references_file.js +2 -0
  19. package/build/generated/bridge_work_order_seed_file.js +2 -0
  20. package/build/generated/contracts_bundle_info.js +3 -3
  21. package/build/generated/index.js +14 -0
  22. package/build/generated/ingress_input.js +2 -0
  23. package/build/generated/ingress_output.js +2 -0
  24. package/build/generated/ingress_resolution_file.js +2 -0
  25. package/build/generated/ingress_summary_file.js +2 -0
  26. package/build/generated/message_template_id_mapping_file.js +2 -0
  27. package/build/generated/run_app_input.js +1 -1
  28. package/build/index.js +4 -3
  29. package/build/local-mode/paths.js +1 -0
  30. package/build/local-mode/setup.js +21 -1
  31. package/build/path-utils.js +68 -0
  32. package/build/runtime/cli_invoker.js +1 -1
  33. package/build/tools/vibe_pm/advisory_review.js +5 -3
  34. package/build/tools/vibe_pm/bridge_build_seed.js +164 -0
  35. package/build/tools/vibe_pm/bridge_confirm_reference.js +91 -0
  36. package/build/tools/vibe_pm/bridge_generate_references.js +258 -0
  37. package/build/tools/vibe_pm/briefing.js +27 -3
  38. package/build/tools/vibe_pm/context.js +79 -0
  39. package/build/tools/vibe_pm/create_work_order.js +200 -3
  40. package/build/tools/vibe_pm/doctor.js +95 -0
  41. package/build/tools/vibe_pm/entity_gate/preflight.js +8 -3
  42. package/build/tools/vibe_pm/export_output.js +14 -13
  43. package/build/tools/vibe_pm/finalize_work.js +78 -40
  44. package/build/tools/vibe_pm/get_decision.js +2 -2
  45. package/build/tools/vibe_pm/index.js +128 -42
  46. package/build/tools/vibe_pm/ingress.js +645 -0
  47. package/build/tools/vibe_pm/ingress_gate.js +116 -0
  48. package/build/tools/vibe_pm/inspect_code.js +90 -20
  49. package/build/tools/vibe_pm/kce/doc_usage.js +4 -9
  50. package/build/tools/vibe_pm/kce/on_finalize.js +2 -2
  51. package/build/tools/vibe_pm/kce/preflight.js +11 -7
  52. package/build/tools/vibe_pm/memory_status.js +11 -8
  53. package/build/tools/vibe_pm/memory_sync.js +11 -8
  54. package/build/tools/vibe_pm/pm_language.js +17 -16
  55. package/build/tools/vibe_pm/python_error.js +115 -0
  56. package/build/tools/vibe_pm/run_app.js +169 -43
  57. package/build/tools/vibe_pm/run_app_podman.js +64 -2
  58. package/build/tools/vibe_pm/search_oss.js +5 -3
  59. package/build/tools/vibe_pm/spec_rag.js +185 -0
  60. package/build/tools/vibe_pm/status.js +50 -3
  61. package/build/tools/vibe_pm/submit_decision.js +2 -2
  62. package/build/tools/vibe_pm/types.js +28 -0
  63. package/build/tools/vibe_pm/undo_last_task.js +9 -2
  64. package/build/tools/vibe_pm/waiter_mapping.js +155 -0
  65. package/build/tools/vibe_pm/zoekt_evidence.js +5 -3
  66. package/build/tools.js +13 -5
  67. package/build/vibe-cli.js +245 -7
  68. package/package.json +5 -4
  69. package/skills/VRIP_INSTALL_MANIFEST_DOCTOR.skill.md +288 -0
  70. package/skills/index.json +14 -0
@@ -1,7 +1,7 @@
1
1
  // adapters/mcp-ts/src/tools/vibe_pm/index.ts
2
2
  // vibe_pm.* MCP tools registration and export
3
3
  import { McpError } from "@modelcontextprotocol/sdk/types.js";
4
- import { briefingInputSchema, briefingOutputSchema, getDecisionInputSchema, getDecisionOutputSchema, submitDecisionInputSchema, submitDecisionOutputSchema, createWorkOrderInputSchema, createWorkOrderOutputSchema, inspectCodeInputSchema, inspectCodeOutputSchema, statusInputSchema, statusOutputSchema, memoryStatusInputSchema, memoryStatusOutputSchema, memorySyncInputSchema, memorySyncOutputSchema, advisoryReviewInputSchema, advisoryReviewOutputSchema, activateInputSchema, activateOutputSchema, repairPlanInputSchema, repairPlanOutputSchema, scaffoldInputSchema, scaffoldOutputSchema, finalizeWorkInputSchema, finalizeWorkOutputSchema, undoLastTaskInputSchema, undoLastTaskOutputSchema, runAppInputSchema, runAppOutputSchema, exportOutputInputSchema, exportOutputOutputSchema, searchOssInputSchema, searchOssOutputSchema, zoektEvidenceInputSchema, zoektEvidenceOutputSchema, doctorOutputSchema, updateOutputSchema } from "./types.js";
4
+ import { briefingInputSchema, briefingOutputSchema, getDecisionInputSchema, getDecisionOutputSchema, submitDecisionInputSchema, submitDecisionOutputSchema, createWorkOrderInputSchema, createWorkOrderOutputSchema, inspectCodeInputSchema, inspectCodeOutputSchema, statusInputSchema, statusOutputSchema, memoryStatusInputSchema, memoryStatusOutputSchema, memorySyncInputSchema, memorySyncOutputSchema, advisoryReviewInputSchema, advisoryReviewOutputSchema, activateInputSchema, activateOutputSchema, repairPlanInputSchema, repairPlanOutputSchema, scaffoldInputSchema, scaffoldOutputSchema, finalizeWorkInputSchema, finalizeWorkOutputSchema, undoLastTaskInputSchema, undoLastTaskOutputSchema, runAppInputSchema, runAppOutputSchema, exportOutputInputSchema, exportOutputOutputSchema, searchOssInputSchema, searchOssOutputSchema, zoektEvidenceInputSchema, zoektEvidenceOutputSchema, ingressInputSchema, ingressOutputSchema, bridgeGenerateReferencesInputSchema, bridgeGenerateReferencesOutputSchema, bridgeConfirmReferenceInputSchema, bridgeConfirmReferenceOutputSchema, bridgeBuildSeedInputSchema, bridgeBuildSeedOutputSchema, doctorOutputSchema, updateOutputSchema } from "./types.js";
5
5
  import { briefing } from "./briefing.js";
6
6
  import { getDecision } from "./get_decision.js";
7
7
  import { submitDecision } from "./submit_decision.js";
@@ -22,13 +22,17 @@ import { runApp } from "./run_app.js";
22
22
  import { exportOutput } from "./export_output.js";
23
23
  import { searchOss } from "./search_oss.js";
24
24
  import { zoektEvidence } from "./zoekt_evidence.js";
25
+ import { ingress } from "./ingress.js";
26
+ import { bridgeGenerateReferences } from "./bridge_generate_references.js";
27
+ import { bridgeConfirmReference } from "./bridge_confirm_reference.js";
28
+ import { bridgeBuildSeed } from "./bridge_build_seed.js";
25
29
  import { gate, gateInputSchema, gateOutputSchema } from "./gate.js";
26
30
  import { forceOverride, forceOverrideInputSchema, forceOverrideOutputSchema } from "./force_override.js";
27
- import { saveRule, saveRuleInputSchema, saveRuleOutputSchema } from "./save_rule.js";
28
- import { listRules, listRulesInputSchema, listRulesOutputSchema } from "./list_rules.js";
29
31
  import { getAuthGate } from "../../auth/index.js";
30
32
  import { ToolErrorOutputSchema } from "../../generated/tool_error_output.js";
31
33
  import { decorateToolOutputText, notifyDesktopBestEffort } from "../../dx/activity.js";
34
+ import { resolveRunId } from "./context.js";
35
+ import { checkIngressGate, isIngressGateRequiredForTool } from "./ingress_gate.js";
32
36
  // ============================================================
33
37
  // Helper Functions
34
38
  // ============================================================
@@ -85,6 +89,24 @@ function errorResult(toolName, error) {
85
89
  details
86
90
  });
87
91
  }
92
+ async function enforceIngressGateIfNeeded(toolName, input) {
93
+ if (!isIngressGateRequiredForTool(toolName))
94
+ return null;
95
+ const basePath = process.cwd();
96
+ const project_id = input && typeof input === "object" && "project_id" in input && typeof input.project_id === "string"
97
+ ? input.project_id
98
+ : undefined;
99
+ const { run_id } = resolveRunId(project_id, basePath);
100
+ const gate = await checkIngressGate({ toolName, basePath, run_id });
101
+ if (gate.status === "BLOCK") {
102
+ return err(toolName, "ingress_gate_blocked", {
103
+ message: gate.message,
104
+ recovery: gate.recovery,
105
+ details: gate.details
106
+ });
107
+ }
108
+ return null;
109
+ }
88
110
  // ============================================================
89
111
  // Tool Handlers (with error handling and structured content)
90
112
  // ============================================================
@@ -107,9 +129,30 @@ async function vibePmBriefing(input) {
107
129
  });
108
130
  }
109
131
  }
132
+ async function vibePmIngress(input) {
133
+ const startedAt = Date.now();
134
+ try {
135
+ const result = await ingress(input);
136
+ const validated = ingressOutputSchema.parse(result);
137
+ return toolResult("vibe_pm.ingress", validated, Date.now() - startedAt);
138
+ }
139
+ catch (e) {
140
+ if (e instanceof McpError) {
141
+ return errorResult("vibe_pm.ingress", e);
142
+ }
143
+ const msg = e instanceof Error ? e.message : String(e);
144
+ return err("vibe_pm.ingress", "ingress_failed", {
145
+ message: msg,
146
+ recovery: "프로젝트 이어가기/새 작업을 확정하기 위한 입력을 확인해 주세요."
147
+ });
148
+ }
149
+ }
110
150
  async function vibePmGetDecision(input) {
111
151
  const startedAt = Date.now();
112
152
  try {
153
+ const blocked = await enforceIngressGateIfNeeded("vibe_pm.get_decision", input);
154
+ if (blocked)
155
+ return blocked;
113
156
  const result = await getDecision(input);
114
157
  const validated = getDecisionOutputSchema.parse(result);
115
158
  return toolResult("vibe_pm.get_decision", validated, Date.now() - startedAt);
@@ -128,6 +171,9 @@ async function vibePmGetDecision(input) {
128
171
  async function vibePmSubmitDecision(input) {
129
172
  const startedAt = Date.now();
130
173
  try {
174
+ const blocked = await enforceIngressGateIfNeeded("vibe_pm.submit_decision", input);
175
+ if (blocked)
176
+ return blocked;
131
177
  const result = await submitDecision(input);
132
178
  const validated = submitDecisionOutputSchema.parse(result);
133
179
  return toolResult("vibe_pm.submit_decision", validated, Date.now() - startedAt);
@@ -146,6 +192,9 @@ async function vibePmSubmitDecision(input) {
146
192
  async function vibePmCreateWorkOrder(input) {
147
193
  const startedAt = Date.now();
148
194
  try {
195
+ const blocked = await enforceIngressGateIfNeeded("vibe_pm.create_work_order", input);
196
+ if (blocked)
197
+ return blocked;
149
198
  const result = await createWorkOrder(input);
150
199
  const validated = createWorkOrderOutputSchema.parse(result);
151
200
  return toolResult("vibe_pm.create_work_order", validated, Date.now() - startedAt);
@@ -164,6 +213,9 @@ async function vibePmCreateWorkOrder(input) {
164
213
  async function vibePmInspectCode(input) {
165
214
  const startedAt = Date.now();
166
215
  try {
216
+ const blocked = await enforceIngressGateIfNeeded("vibe_pm.inspect_code", input);
217
+ if (blocked)
218
+ return blocked;
167
219
  const result = await inspectCode(input);
168
220
  const validated = inspectCodeOutputSchema.parse(result);
169
221
  return toolResult("vibe_pm.inspect_code", validated, Date.now() - startedAt);
@@ -371,6 +423,9 @@ async function vibePmScaffold(input) {
371
423
  async function vibePmFinalizeWork(input) {
372
424
  const startedAt = Date.now();
373
425
  try {
426
+ const blocked = await enforceIngressGateIfNeeded("vibe_pm.finalize_work", input);
427
+ if (blocked)
428
+ return blocked;
374
429
  const result = await finalizeWork(input);
375
430
  const validated = finalizeWorkOutputSchema.parse(result);
376
431
  return toolResult("vibe_pm.finalize_work", validated, Date.now() - startedAt);
@@ -389,6 +444,9 @@ async function vibePmFinalizeWork(input) {
389
444
  async function vibePmUndoLastTask(input) {
390
445
  const startedAt = Date.now();
391
446
  try {
447
+ const blocked = await enforceIngressGateIfNeeded("vibe_pm.undo_last_task", input);
448
+ if (blocked)
449
+ return blocked;
392
450
  const result = await undoLastTask(input);
393
451
  const validated = undoLastTaskOutputSchema.parse(result);
394
452
  return toolResult("vibe_pm.undo_last_task", validated, Date.now() - startedAt);
@@ -407,6 +465,9 @@ async function vibePmUndoLastTask(input) {
407
465
  async function vibePmRunApp(input) {
408
466
  const startedAt = Date.now();
409
467
  try {
468
+ const blocked = await enforceIngressGateIfNeeded("vibe_pm.run_app", input);
469
+ if (blocked)
470
+ return blocked;
410
471
  const result = await runApp(input);
411
472
  const validated = runAppOutputSchema.parse(result);
412
473
  return toolResult("vibe_pm.run_app", validated, Date.now() - startedAt);
@@ -476,75 +537,93 @@ async function vibePmZoektEvidence(input) {
476
537
  });
477
538
  }
478
539
  }
479
- async function vibePmGate(input) {
540
+ async function vibePmBridgeGenerateReferences(input) {
480
541
  const startedAt = Date.now();
481
542
  try {
482
- const result = await gate(input);
483
- const validated = gateOutputSchema.parse(result);
484
- return toolResult("vibe_pm.gate", validated, Date.now() - startedAt);
543
+ const result = await bridgeGenerateReferences(input);
544
+ const validated = bridgeGenerateReferencesOutputSchema.parse(result);
545
+ return toolResult("vibe_pm.bridge_generate_references", validated, Date.now() - startedAt);
485
546
  }
486
547
  catch (e) {
487
548
  if (e instanceof McpError) {
488
- return errorResult("vibe_pm.gate", e);
549
+ return errorResult("vibe_pm.bridge_generate_references", e);
489
550
  }
490
551
  const msg = e instanceof Error ? e.message : String(e);
491
- return err("vibe_pm.gate", "gate_failed", {
552
+ return err("vibe_pm.bridge_generate_references", "bridge_generate_references_failed", {
492
553
  message: msg,
493
- recovery: "work_order 형식을 확인하고 다시 시도해주세요."
554
+ recovery: "키워드/의도를 구체적으로 적은 뒤 다시 시도해주세요."
494
555
  });
495
556
  }
496
557
  }
497
- async function vibePmForceOverride(input) {
558
+ async function vibePmBridgeConfirmReference(input) {
498
559
  const startedAt = Date.now();
499
560
  try {
500
- const result = await forceOverride(input);
501
- const validated = forceOverrideOutputSchema.parse(result);
502
- return toolResult("vibe_pm.force_override", validated, Date.now() - startedAt);
561
+ const result = await bridgeConfirmReference(input);
562
+ const validated = bridgeConfirmReferenceOutputSchema.parse(result);
563
+ return toolResult("vibe_pm.bridge_confirm_reference", validated, Date.now() - startedAt);
503
564
  }
504
565
  catch (e) {
505
566
  if (e instanceof McpError) {
506
- return errorResult("vibe_pm.force_override", e);
567
+ return errorResult("vibe_pm.bridge_confirm_reference", e);
507
568
  }
508
569
  const msg = e instanceof Error ? e.message : String(e);
509
- return err("vibe_pm.force_override", "force_override_failed", {
570
+ return err("vibe_pm.bridge_confirm_reference", "bridge_confirm_reference_failed", {
510
571
  message: msg,
511
- recovery: "acknowledge_risks: true 반드시 포함해야 합니다."
572
+ recovery: "A/B/C 하나로 선택한 다시 시도해주세요."
512
573
  });
513
574
  }
514
575
  }
515
- async function vibePmSaveRule(input) {
576
+ async function vibePmBridgeBuildSeed(input) {
577
+ const startedAt = Date.now();
578
+ try {
579
+ const result = await bridgeBuildSeed(input);
580
+ const validated = bridgeBuildSeedOutputSchema.parse(result);
581
+ return toolResult("vibe_pm.bridge_build_seed", validated, Date.now() - startedAt);
582
+ }
583
+ catch (e) {
584
+ if (e instanceof McpError) {
585
+ return errorResult("vibe_pm.bridge_build_seed", e);
586
+ }
587
+ const msg = e instanceof Error ? e.message : String(e);
588
+ return err("vibe_pm.bridge_build_seed", "bridge_build_seed_failed", {
589
+ message: msg,
590
+ recovery: "레퍼런스 확정이 완료되었는지 확인한 뒤 다시 시도해주세요."
591
+ });
592
+ }
593
+ }
594
+ async function vibePmGate(input) {
516
595
  const startedAt = Date.now();
517
596
  try {
518
- const result = await saveRule(input);
519
- const validated = saveRuleOutputSchema.parse(result);
520
- return toolResult("vibe_pm.save_rule", validated, Date.now() - startedAt);
597
+ const result = await gate(input);
598
+ const validated = gateOutputSchema.parse(result);
599
+ return toolResult("vibe_pm.gate", validated, Date.now() - startedAt);
521
600
  }
522
601
  catch (e) {
523
602
  if (e instanceof McpError) {
524
- return errorResult("vibe_pm.save_rule", e);
603
+ return errorResult("vibe_pm.gate", e);
525
604
  }
526
605
  const msg = e instanceof Error ? e.message : String(e);
527
- return err("vibe_pm.save_rule", "save_rule_failed", {
606
+ return err("vibe_pm.gate", "gate_failed", {
528
607
  message: msg,
529
- recovery: "규칙 제목, 트리거, 액션을 확인하세요."
608
+ recovery: "work_order 형식을 확인하고 다시 시도해주세요."
530
609
  });
531
610
  }
532
611
  }
533
- async function vibePmListRules(input) {
612
+ async function vibePmForceOverride(input) {
534
613
  const startedAt = Date.now();
535
614
  try {
536
- const result = await listRules(input);
537
- const validated = listRulesOutputSchema.parse(result);
538
- return toolResult("vibe_pm.list_rules", validated, Date.now() - startedAt);
615
+ const result = await forceOverride(input);
616
+ const validated = forceOverrideOutputSchema.parse(result);
617
+ return toolResult("vibe_pm.force_override", validated, Date.now() - startedAt);
539
618
  }
540
619
  catch (e) {
541
620
  if (e instanceof McpError) {
542
- return errorResult("vibe_pm.list_rules", e);
621
+ return errorResult("vibe_pm.force_override", e);
543
622
  }
544
623
  const msg = e instanceof Error ? e.message : String(e);
545
- return err("vibe_pm.list_rules", "list_rules_failed", {
624
+ return err("vibe_pm.force_override", "force_override_failed", {
546
625
  message: msg,
547
- recovery: ".vibe 폴더가 있는지 확인하세요."
626
+ recovery: "acknowledge_risks: true 반드시 포함해야 합니다."
548
627
  });
549
628
  }
550
629
  }
@@ -555,6 +634,7 @@ export function defineVibePmTools() {
555
634
  return {
556
635
  // Input schemas (for validation)
557
636
  briefingInputSchema,
637
+ ingressInputSchema,
558
638
  getDecisionInputSchema,
559
639
  submitDecisionInputSchema,
560
640
  createWorkOrderInputSchema,
@@ -574,12 +654,14 @@ export function defineVibePmTools() {
574
654
  exportOutputInputSchema,
575
655
  searchOssInputSchema,
576
656
  zoektEvidenceInputSchema,
657
+ bridgeGenerateReferencesInputSchema,
658
+ bridgeConfirmReferenceInputSchema,
659
+ bridgeBuildSeedInputSchema,
577
660
  gateInputSchema,
578
661
  forceOverrideInputSchema,
579
- saveRuleInputSchema,
580
- listRulesInputSchema,
581
662
  // Tool handlers
582
663
  vibePmBriefing,
664
+ vibePmIngress,
583
665
  vibePmGetDecision,
584
666
  vibePmSubmitDecision,
585
667
  vibePmCreateWorkOrder,
@@ -599,10 +681,11 @@ export function defineVibePmTools() {
599
681
  vibePmExportOutput,
600
682
  vibePmSearchOss,
601
683
  vibePmZoektEvidence,
684
+ vibePmBridgeGenerateReferences,
685
+ vibePmBridgeConfirmReference,
686
+ vibePmBridgeBuildSeed,
602
687
  vibePmGate,
603
- vibePmForceOverride,
604
- vibePmSaveRule,
605
- vibePmListRules
688
+ vibePmForceOverride
606
689
  };
607
690
  }
608
691
  // ============================================================
@@ -611,6 +694,8 @@ export function defineVibePmTools() {
611
694
  export const VIBE_PM_TOOL_DESCRIPTIONS = {
612
695
  "vibe_pm.briefing": `프로젝트를 시작하거나 재개합니다. 사용자의 아이디어를 받아 구조화합니다.
613
696
  사용 시점: 사용자가 "시작해줘" 또는 새 아이디어를 설명할 때`,
697
+ "vibe_pm.ingress": `프로젝트를 이어가기/새 작업 시작을 확정하고, 필요한 사전 점검(컨텍스트 스캔)을 수행합니다.
698
+ 사용 시점: 기존 프로젝트를 이어서 할지, 새 작업을 시작할지 확정해야 할 때`,
614
699
  "vibe_pm.get_decision": `현재 결재가 필요한 안건을 조회합니다.
615
700
  사용 시점: 구현 전 승인이 필요할 때`,
616
701
  "vibe_pm.submit_decision": `결재를 제출합니다.
@@ -648,6 +733,12 @@ export const VIBE_PM_TOOL_DESCRIPTIONS = {
648
733
  사용 시점: export_output용 템플릿을 고르기 전에 후보를 좁히고 싶을 때`,
649
734
  "vibe_pm.zoekt_evidence": `로컬 루트들에서 패턴 증거를 수집합니다(zoekt/rg/python_scan).
650
735
  사용 시점: 특정 코드 패턴이 실제로 얼마나 쓰이는지 근거가 필요할 때`,
736
+ "vibe_pm.bridge_generate_references": `모호한 요구를 레퍼런스 후보(A/B/C)로 정리하고 파일로 저장합니다.
737
+ 사용 시점: 구현 전에 "어떤 스타일/유사 제품 기준으로 만들지"를 확정해야 할 때`,
738
+ "vibe_pm.bridge_confirm_reference": `레퍼런스 후보 중 하나(A/B/C)를 확정하고 확인 기록을 남깁니다.
739
+ 사용 시점: 레퍼런스 후보를 만든 뒤, 기준을 하나로 고정할 때`,
740
+ "vibe_pm.bridge_build_seed": `확정된 레퍼런스를 기반으로 작업 seed를 생성합니다.
741
+ 사용 시점: 레퍼런스 확정 후, create_work_order의 기준을 고정하고 싶을 때`,
651
742
  "vibe_pm.export_output": `구현된 기능을 원하는 형태로 내보냅니다. (문서/API/CLI 등)
652
743
  사용 시점: 기능 구현 및 검수 후, 결과물을 다른 형태로 배포/공유하고 싶을 때`,
653
744
  "vibe_pm.gate": `작업 지시서가 시스템 설계 규칙을 준수하는지 검증합니다. (Schema/Path/Runtime/Semgrep Gate)
@@ -655,10 +746,5 @@ export const VIBE_PM_TOOL_DESCRIPTIONS = {
655
746
  BLOCK이 없으면 실행 가능, BLOCK이 있으면 수정이 필요합니다.`,
656
747
  "vibe_pm.force_override": `차단된 작업을 강제로 실행할 수 있는 탈출 경로입니다. (P2-1)
657
748
  사용 시점: 정책에 의해 차단되었지만 긴급히 실행이 필요할 때
658
- ⚠ 주의: acknowledge_risks=true 필수, 모든 사용은 감사 로그에 기록됩니다.`,
659
- "vibe_pm.save_rule": `프로젝트별 워크플로우 규칙을 저장합니다.
660
- 사용 시점: 사용자가 "~할 때마다 ~해", "항상 ~해줘" 같은 반복 패턴을 지시할 때
661
- 저장 위치: .vibe/project_rules.md`,
662
- "vibe_pm.list_rules": `현재 프로젝트에 저장된 워크플로우 규칙 목록을 조회합니다.
663
- 사용 시점: 작업 시작 전 적용할 규칙을 확인하고 싶을 때`
749
+ ⚠ 주의: acknowledge_risks=true 필수, 모든 사용은 감사 로그에 기록됩니다.`
664
750
  };