@vibe-assurance/cli 1.7.7 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -55,15 +55,6 @@ npm install -g @vibe-assurance/cli
55
55
 
56
56
  Once configured, your AI coding agent has access to these tools:
57
57
 
58
- ### Roles (AI Analyst Prompts)
59
-
60
- | Tool | Description |
61
- |------|-------------|
62
- | `vibe_get_role` | Get an AI analyst role prompt by ID |
63
- | `vibe_list_roles` | List all available roles |
64
- | `vibe_update_role` | Update a role's system prompt |
65
- | `vibe_create_role` | Create a new custom role |
66
-
67
58
  ### Context & Templates
68
59
 
69
60
  | Tool | Description |
@@ -91,10 +82,19 @@ Once configured, your AI coding agent has access to these tools:
91
82
  | `RISK` | Risk Register Entries | RISK-001 |
92
83
  | `VULNERABILITY` | Security Vulnerabilities | VUL-059 |
93
84
  | `REPORT` | Security/Audit Reports | RPT-2026-001 |
94
- | `POLICY` | Governance Policies | POL-001 |
95
85
  | `PLAN` | Strategic & Technical Plans | PLAN-2026-002 |
96
86
  | `CONFIG` | Configuration Documentation | CFG-001 |
97
- | `SOP` | Standard Operating Procedures | SOP-001 |
87
+ | `ARCHITECTURE` | Architecture Documentation | ARCH-001 |
88
+
89
+ ### Strategic Plans
90
+
91
+ | Tool | Description |
92
+ |------|-------------|
93
+ | `vibe_get_strategic_plans` | List strategic plans (filter by status) |
94
+ | `vibe_store_plan` | Create a new strategic plan |
95
+ | `vibe_update_plan` | Update plan content, title, or metadata |
96
+ | `vibe_update_plan_status` | Update plan status (Draft/Active/Completed/Closed) |
97
+ | `vibe_delete_plan` | Delete a strategic plan |
98
98
 
99
99
  ### Risk Register
100
100
 
@@ -114,26 +114,6 @@ Once configured, your AI coding agent has access to these tools:
114
114
  | `vibe_get_vulnerability` | Get specific vulnerability by ID |
115
115
  | `vibe_update_vulnerability` | Update vulnerability status or link to CR |
116
116
 
117
- ### Strategic Plans
118
-
119
- | Tool | Description |
120
- |------|-------------|
121
- | `vibe_get_strategic_plans` | List strategic plans (PLAN artifacts) |
122
- | `vibe_update_plan_status` | Update plan status (Draft/Active/Completed/Closed) |
123
-
124
- ### Policies & SOPs
125
-
126
- | Tool | Description |
127
- |------|-------------|
128
- | `vibe_list_policies` | List project's policies |
129
- | `vibe_store_policy` | Create a new policy |
130
- | `vibe_get_policy` | Get specific policy by ID |
131
- | `vibe_update_policy` | Update policy content or metadata |
132
- | `vibe_list_sops` | List project's SOPs |
133
- | `vibe_store_sop` | Create a new SOP |
134
- | `vibe_get_sop` | Get specific SOP by ID |
135
- | `vibe_update_sop` | Update SOP content or metadata |
136
-
137
117
  ## Example Session
138
118
 
139
119
  ```
@@ -142,7 +122,6 @@ User: Create a change request for adding user authentication
142
122
  AI Agent: I'll help you create a change request. Let me get your context first.
143
123
 
144
124
  [Calls vibe_get_context]
145
- [Calls vibe_get_role("implementation-planner")]
146
125
  [Calls vibe_get_template("change-request")]
147
126
 
148
127
  Based on your governance context, your next CR ID is CR-2026-001.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-assurance/cli",
3
- "version": "1.7.7",
3
+ "version": "1.10.0",
4
4
  "description": "Vibe Assurance CLI - Connect AI coding agents to your governance platform via MCP",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/api/client.js CHANGED
@@ -29,7 +29,7 @@ const API_BASE_URL = process.env.VIBE_API_URL || getEnvironmentUrl(DEFAULT_ENVIR
29
29
  * @returns {Promise<import('axios').AxiosInstance>}
30
30
  */
31
31
  async function createClient() {
32
- const creds = await getCredentials();
32
+ let creds = await getCredentials();
33
33
  if (!creds || !creds.accessToken) {
34
34
  throw new Error('Not authenticated. Run: vibe login');
35
35
  }
@@ -37,13 +37,37 @@ async function createClient() {
37
37
  // CR-2026-061: Get API URL from stored environment
38
38
  const apiBaseUrl = await getApiBaseUrl();
39
39
 
40
+ // Pre-emptive token refresh: If token expires within 5 minutes, refresh now
41
+ // This avoids race conditions where the token expires during an API call
42
+ if (creds.expiresAt && creds.refreshToken) {
43
+ const expiresAt = new Date(creds.expiresAt);
44
+ const now = new Date();
45
+ const bufferMs = 5 * 60 * 1000; // 5 minutes
46
+
47
+ if (expiresAt.getTime() - bufferMs < now.getTime()) {
48
+ try {
49
+ const newTokens = await refreshToken(creds.refreshToken);
50
+ // Preserve existing credentials (environment, projectId, user info)
51
+ creds = {
52
+ ...creds,
53
+ ...newTokens
54
+ };
55
+ await storeCredentials(creds);
56
+ } catch (refreshError) {
57
+ // Pre-emptive refresh failed - will try again on 401
58
+ // Don't throw here, let the request proceed with old token
59
+ console.error('Pre-emptive token refresh failed, will retry on 401');
60
+ }
61
+ }
62
+ }
63
+
40
64
  // CR-2026-043: Get current project ID for scoping
41
65
  const projectId = await getProjectId();
42
66
 
43
67
  const headers = {
44
68
  'Authorization': `Bearer ${creds.accessToken}`,
45
69
  'Content-Type': 'application/json',
46
- 'User-Agent': 'vibe-cli/1.7.0'
70
+ 'User-Agent': 'vibe-cli/1.10.0'
47
71
  };
48
72
 
49
73
  // CR-2026-043: Add project header if available
@@ -69,7 +93,14 @@ async function createClient() {
69
93
 
70
94
  try {
71
95
  const newTokens = await refreshToken(creds.refreshToken);
72
- await storeCredentials(newTokens);
96
+
97
+ // CRITICAL: Preserve existing credentials (environment, projectId, user info)
98
+ // when storing new tokens. Only update token-related fields.
99
+ const currentCreds = await getCredentials();
100
+ await storeCredentials({
101
+ ...currentCreds, // Preserve environment, projectId, username, email, role, etc.
102
+ ...newTokens // Update accessToken, refreshToken, expiresAt
103
+ });
73
104
 
74
105
  // Update the failed request with new token
75
106
  originalRequest.headers['Authorization'] = `Bearer ${newTokens.accessToken}`;
@@ -79,7 +79,7 @@ async function login() {
79
79
 
80
80
  // For license errors, redirect to pricing page instead of showing error HTML
81
81
  if (error === 'cli_access_denied') {
82
- res.writeHead(302, { 'Location': 'https://vibeassurance.app/pricing' });
82
+ res.writeHead(302, { 'Location': 'https://vibeassurance.app/pricing.html' });
83
83
  res.end();
84
84
  } else {
85
85
  res.writeHead(400, { 'Content-Type': 'text/html' });
package/src/mcp/tools.js CHANGED
@@ -223,7 +223,7 @@ const tools = [
223
223
  properties: {
224
224
  type: {
225
225
  type: 'string',
226
- enum: ['CR', 'RISK', 'VULNERABILITY', 'REPORT', 'POLICY', 'PLAN', 'ARCHITECTURE', 'CONFIG', 'SOP'],
226
+ enum: ['CR', 'RISK', 'VULNERABILITY', 'REPORT', 'STANDARD', 'PLAN', 'ARCHITECTURE', 'CONFIG'],
227
227
  description: 'Type of artifact'
228
228
  },
229
229
  artifactId: {
@@ -348,7 +348,7 @@ const tools = [
348
348
  properties: {
349
349
  type: {
350
350
  type: 'string',
351
- enum: ['CR', 'RISK', 'VULNERABILITY', 'REPORT', 'POLICY', 'PLAN', 'ARCHITECTURE', 'CONFIG', 'SOP'],
351
+ enum: ['CR', 'RISK', 'VULNERABILITY', 'REPORT', 'STANDARD', 'PLAN', 'ARCHITECTURE', 'CONFIG'],
352
352
  description: 'Filter by artifact type. Use "PLAN" to find strategic plans.'
353
353
  },
354
354
  status: {
@@ -435,6 +435,84 @@ const tools = [
435
435
  }
436
436
  },
437
437
 
438
+ {
439
+ name: 'vibe_store_plan',
440
+ description: 'Create a new strategic plan. Plans contain CR roadmaps for implementing features or initiatives.',
441
+ inputSchema: {
442
+ type: 'object',
443
+ properties: {
444
+ planId: {
445
+ type: 'string',
446
+ description: 'Unique plan ID (e.g., "PLAN-2026-001")'
447
+ },
448
+ title: {
449
+ type: 'string',
450
+ description: 'Title of the plan (e.g., "Authentication System Overhaul")'
451
+ },
452
+ content: {
453
+ type: 'string',
454
+ description: 'Full plan content in markdown format (include CR roadmap table)'
455
+ },
456
+ status: {
457
+ type: 'string',
458
+ enum: ['Draft', 'Active', 'Completed', 'Closed'],
459
+ description: 'Plan status (default: Draft)'
460
+ },
461
+ metadata: {
462
+ type: 'object',
463
+ description: 'Additional metadata (e.g., priority, target date)',
464
+ additionalProperties: true
465
+ }
466
+ },
467
+ required: ['planId', 'title', 'content']
468
+ },
469
+ handler: async (params) => {
470
+ return await api.post('/api/mcp/artifacts', {
471
+ type: 'PLAN',
472
+ artifactId: params.planId,
473
+ title: params.title,
474
+ content: params.content,
475
+ status: params.status || 'Draft',
476
+ metadata: params.metadata
477
+ });
478
+ }
479
+ },
480
+
481
+ {
482
+ name: 'vibe_update_plan',
483
+ description: 'Update a strategic plan\'s content, title, status, or metadata.',
484
+ inputSchema: {
485
+ type: 'object',
486
+ properties: {
487
+ planId: {
488
+ type: 'string',
489
+ description: 'The plan artifact ID (e.g., "PLAN-2026-001")'
490
+ },
491
+ title: {
492
+ type: 'string',
493
+ description: 'Updated title'
494
+ },
495
+ content: {
496
+ type: 'string',
497
+ description: 'Updated content'
498
+ },
499
+ status: {
500
+ type: 'string',
501
+ enum: ['Draft', 'Active', 'Completed', 'Closed'],
502
+ description: 'Updated status'
503
+ },
504
+ metadata: {
505
+ type: 'object',
506
+ description: 'Updated metadata'
507
+ }
508
+ },
509
+ required: ['planId']
510
+ },
511
+ handler: async ({ planId, ...updates }) => {
512
+ return await api.put(`/api/mcp/artifacts/${planId}`, updates);
513
+ }
514
+ },
515
+
438
516
  {
439
517
  name: 'vibe_update_plan_status',
440
518
  description: 'Update a strategic plan\'s status. Use when all CRs from a plan are complete to mark it as Completed.',
@@ -458,6 +536,24 @@ const tools = [
458
536
  }
459
537
  },
460
538
 
539
+ {
540
+ name: 'vibe_delete_plan',
541
+ description: 'Delete a strategic plan. This is permanent and cannot be undone.',
542
+ inputSchema: {
543
+ type: 'object',
544
+ properties: {
545
+ planId: {
546
+ type: 'string',
547
+ description: 'The plan artifact ID to delete (e.g., "PLAN-2026-001")'
548
+ }
549
+ },
550
+ required: ['planId']
551
+ },
552
+ handler: async ({ planId }) => {
553
+ return await api.delete(`/api/mcp/artifacts/${planId}`);
554
+ }
555
+ },
556
+
461
557
  // ============================================================================
462
558
  // RISK MANAGEMENT TOOLS
463
559
  // ============================================================================
@@ -659,6 +755,10 @@ const tools = [
659
755
  location: {
660
756
  type: 'string',
661
757
  description: 'File path or component where vulnerability exists'
758
+ },
759
+ remediationPlanId: {
760
+ type: 'string',
761
+ description: 'Link to remediation plan (e.g., "RMP-VUL-001")'
662
762
  }
663
763
  },
664
764
  required: ['vulId', 'title', 'description', 'severity']
@@ -688,7 +788,7 @@ const tools = [
688
788
 
689
789
  {
690
790
  name: 'vibe_update_vulnerability',
691
- description: 'Update a vulnerability\'s status, severity, or link it to a remediation CR.',
791
+ description: 'Update a vulnerability\'s status, severity, link it to a remediation CR, or link to a remediation plan.',
692
792
  inputSchema: {
693
793
  type: 'object',
694
794
  properties: {
@@ -709,6 +809,10 @@ const tools = [
709
809
  relatedCR: {
710
810
  type: 'string',
711
811
  description: 'Link to remediation CR (e.g., "CR-2026-042")'
812
+ },
813
+ remediationPlanId: {
814
+ type: 'string',
815
+ description: 'Link to remediation plan (e.g., "RMP-VUL-001")'
712
816
  }
713
817
  },
714
818
  required: ['vulId']
@@ -719,139 +823,19 @@ const tools = [
719
823
  },
720
824
 
721
825
  // ============================================================================
722
- // SOP MANAGEMENT TOOLS (CR-2026-054)
723
- // ============================================================================
724
-
725
- {
726
- name: 'vibe_list_sops',
727
- description: 'List all Standard Operating Procedures (SOPs) for the project. SOPs define step-by-step procedures for operational tasks.',
728
- inputSchema: {
729
- type: 'object',
730
- properties: {
731
- status: {
732
- type: 'string',
733
- enum: ['Draft', 'Active', 'Completed', 'Closed'],
734
- description: 'Filter by SOP status'
735
- },
736
- category: {
737
- type: 'string',
738
- description: 'Filter by category (e.g., "Security", "HR", "SDLC", "Change Management")'
739
- }
740
- }
741
- },
742
- handler: async (params = {}) => {
743
- const query = new URLSearchParams();
744
- if (params.status) query.set('status', params.status);
745
- if (params.category) query.set('category', params.category);
746
- const queryString = query.toString();
747
- const path = queryString ? `/api/mcp/sops?${queryString}` : '/api/mcp/sops';
748
- return await api.get(path);
749
- }
750
- },
751
-
752
- {
753
- name: 'vibe_store_sop',
754
- description: 'Create a new Standard Operating Procedure (SOP). SOPs define step-by-step procedures for operational tasks like onboarding, offboarding, access reviews, etc.',
755
- inputSchema: {
756
- type: 'object',
757
- properties: {
758
- sopId: {
759
- type: 'string',
760
- description: 'Unique SOP ID (e.g., "SOP-001", "SOP-SDLC-001")'
761
- },
762
- title: {
763
- type: 'string',
764
- description: 'Title of the SOP (e.g., "Employee Onboarding Checklist")'
765
- },
766
- content: {
767
- type: 'string',
768
- description: 'Full SOP content in markdown format'
769
- },
770
- status: {
771
- type: 'string',
772
- enum: ['Draft', 'Active', 'Completed', 'Closed'],
773
- description: 'SOP status (default: Active)'
774
- },
775
- metadata: {
776
- type: 'object',
777
- description: 'Additional metadata (e.g., category, version, owner)',
778
- additionalProperties: true
779
- }
780
- },
781
- required: ['sopId', 'title', 'content']
782
- },
783
- handler: async (params) => {
784
- return await api.post('/api/mcp/sops', params);
785
- }
786
- },
787
-
788
- {
789
- name: 'vibe_get_sop',
790
- description: 'Get a specific SOP by ID with full content.',
791
- inputSchema: {
792
- type: 'object',
793
- properties: {
794
- sopId: {
795
- type: 'string',
796
- description: 'The SOP ID to retrieve (e.g., "SOP-001")'
797
- }
798
- },
799
- required: ['sopId']
800
- },
801
- handler: async ({ sopId }) => {
802
- return await api.get(`/api/mcp/sops/${sopId}`);
803
- }
804
- },
805
-
806
- {
807
- name: 'vibe_update_sop',
808
- description: 'Update an existing SOP\'s content, status, or metadata.',
809
- inputSchema: {
810
- type: 'object',
811
- properties: {
812
- sopId: {
813
- type: 'string',
814
- description: 'The SOP ID to update'
815
- },
816
- title: {
817
- type: 'string',
818
- description: 'Updated title'
819
- },
820
- content: {
821
- type: 'string',
822
- description: 'Updated content'
823
- },
824
- status: {
825
- type: 'string',
826
- enum: ['Draft', 'Active', 'Completed', 'Closed'],
827
- description: 'Updated status'
828
- },
829
- metadata: {
830
- type: 'object',
831
- description: 'Updated metadata'
832
- }
833
- },
834
- required: ['sopId']
835
- },
836
- handler: async ({ sopId, ...updates }) => {
837
- return await api.put(`/api/mcp/sops/${sopId}`, updates);
838
- }
839
- },
840
-
841
- // ============================================================================
842
- // POLICY MANAGEMENT TOOLS (CR-2026-054)
826
+ // STANDARDS MANAGEMENT TOOLS (CR-2026-063: Renamed from Policies)
843
827
  // ============================================================================
844
828
 
845
829
  {
846
- name: 'vibe_list_policies',
847
- description: 'List all policies for the project. Policies define organizational rules and guidelines.',
830
+ name: 'vibe_list_standards',
831
+ description: 'List all standards for the project. Standards define organizational coding standards, security guidelines, and best practices.',
848
832
  inputSchema: {
849
833
  type: 'object',
850
834
  properties: {
851
835
  status: {
852
836
  type: 'string',
853
837
  enum: ['Draft', 'Active', 'Completed', 'Closed'],
854
- description: 'Filter by policy status'
838
+ description: 'Filter by standard status'
855
839
  },
856
840
  category: {
857
841
  type: 'string',
@@ -864,33 +848,33 @@ const tools = [
864
848
  if (params.status) query.set('status', params.status);
865
849
  if (params.category) query.set('category', params.category);
866
850
  const queryString = query.toString();
867
- const path = queryString ? `/api/mcp/policies?${queryString}` : '/api/mcp/policies';
851
+ const path = queryString ? `/api/mcp/standards?${queryString}` : '/api/mcp/standards';
868
852
  return await api.get(path);
869
853
  }
870
854
  },
871
855
 
872
856
  {
873
- name: 'vibe_store_policy',
874
- description: 'Create a new policy document. Policies define organizational rules and guidelines for security, HR, SDLC, etc.',
857
+ name: 'vibe_store_standard',
858
+ description: 'Create a new standard document. Standards define organizational coding standards, security guidelines, and best practices.',
875
859
  inputSchema: {
876
860
  type: 'object',
877
861
  properties: {
878
- policyId: {
862
+ standardId: {
879
863
  type: 'string',
880
- description: 'Unique policy ID (e.g., "POL-001", "POL-SEC-001")'
864
+ description: 'Unique standard ID (e.g., "STD-001", "STD-SEC-001")'
881
865
  },
882
866
  title: {
883
867
  type: 'string',
884
- description: 'Title of the policy (e.g., "Information Security Policy")'
868
+ description: 'Title of the standard (e.g., "Secure Coding Standard")'
885
869
  },
886
870
  content: {
887
871
  type: 'string',
888
- description: 'Full policy content in markdown format'
872
+ description: 'Full standard content in markdown format'
889
873
  },
890
874
  status: {
891
875
  type: 'string',
892
876
  enum: ['Draft', 'Active', 'Completed', 'Closed'],
893
- description: 'Policy status (default: Active)'
877
+ description: 'Standard status (default: Active)'
894
878
  },
895
879
  metadata: {
896
880
  type: 'object',
@@ -898,40 +882,40 @@ const tools = [
898
882
  additionalProperties: true
899
883
  }
900
884
  },
901
- required: ['policyId', 'title', 'content']
885
+ required: ['standardId', 'title', 'content']
902
886
  },
903
887
  handler: async (params) => {
904
- return await api.post('/api/mcp/policies', params);
888
+ return await api.post('/api/mcp/standards', params);
905
889
  }
906
890
  },
907
891
 
908
892
  {
909
- name: 'vibe_get_policy',
910
- description: 'Get a specific policy by ID with full content.',
893
+ name: 'vibe_get_standard',
894
+ description: 'Get a specific standard by ID with full content.',
911
895
  inputSchema: {
912
896
  type: 'object',
913
897
  properties: {
914
- policyId: {
898
+ standardId: {
915
899
  type: 'string',
916
- description: 'The policy ID to retrieve (e.g., "POL-001")'
900
+ description: 'The standard ID to retrieve (e.g., "STD-001")'
917
901
  }
918
902
  },
919
- required: ['policyId']
903
+ required: ['standardId']
920
904
  },
921
- handler: async ({ policyId }) => {
922
- return await api.get(`/api/mcp/policies/${policyId}`);
905
+ handler: async ({ standardId }) => {
906
+ return await api.get(`/api/mcp/standards/${standardId}`);
923
907
  }
924
908
  },
925
909
 
926
910
  {
927
- name: 'vibe_update_policy',
928
- description: 'Update an existing policy\'s content, status, or metadata.',
911
+ name: 'vibe_update_standard',
912
+ description: 'Update an existing standard\'s content, status, or metadata.',
929
913
  inputSchema: {
930
914
  type: 'object',
931
915
  properties: {
932
- policyId: {
916
+ standardId: {
933
917
  type: 'string',
934
- description: 'The policy ID to update'
918
+ description: 'The standard ID to update'
935
919
  },
936
920
  title: {
937
921
  type: 'string',
@@ -951,10 +935,10 @@ const tools = [
951
935
  description: 'Updated metadata'
952
936
  }
953
937
  },
954
- required: ['policyId']
938
+ required: ['standardId']
955
939
  },
956
- handler: async ({ policyId, ...updates }) => {
957
- return await api.put(`/api/mcp/policies/${policyId}`, updates);
940
+ handler: async ({ standardId, ...updates }) => {
941
+ return await api.put(`/api/mcp/standards/${standardId}`, updates);
958
942
  }
959
943
  }
960
944
  ];