@mytechtoday/augment-extensions 1.2.2 → 1.3.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.
Files changed (57) hide show
  1. package/augment-extensions/visual-design/CHANGELOG.md +132 -0
  2. package/augment-extensions/visual-design/README.md +255 -0
  3. package/augment-extensions/visual-design/__tests__/README.md +119 -0
  4. package/augment-extensions/visual-design/__tests__/style-selector.test.ts +172 -0
  5. package/augment-extensions/visual-design/__tests__/vendor-styles.test.ts +214 -0
  6. package/augment-extensions/visual-design/domains/other/ai-prompt-helper.ts +157 -0
  7. package/augment-extensions/visual-design/domains/other/dotnet-application.ts +156 -0
  8. package/augment-extensions/visual-design/domains/other/linux-platform.ts +156 -0
  9. package/augment-extensions/visual-design/domains/other/mobile-application.ts +157 -0
  10. package/augment-extensions/visual-design/domains/other/motion-picture.ts +156 -0
  11. package/augment-extensions/visual-design/domains/other/os-application.ts +156 -0
  12. package/augment-extensions/visual-design/domains/other/print-campaigns.ts +158 -0
  13. package/augment-extensions/visual-design/domains/other/web-app.ts +157 -0
  14. package/augment-extensions/visual-design/domains/other/website.ts +161 -0
  15. package/augment-extensions/visual-design/domains/other/windows-platform.ts +156 -0
  16. package/augment-extensions/visual-design/domains/web-page-styles/amazon-cloudscape.ts +506 -0
  17. package/augment-extensions/visual-design/domains/web-page-styles/google-modern.ts +615 -0
  18. package/augment-extensions/visual-design/domains/web-page-styles/microsoft-fluent.ts +531 -0
  19. package/augment-extensions/visual-design/examples/README.md +97 -0
  20. package/augment-extensions/visual-design/examples/ai-prompt-generation.md +233 -0
  21. package/augment-extensions/visual-design/examples/basic-usage.md +216 -0
  22. package/augment-extensions/visual-design/examples/domain-workflows.md +257 -0
  23. package/augment-extensions/visual-design/examples/vendor-comparison.md +247 -0
  24. package/augment-extensions/visual-design/module.json +78 -0
  25. package/augment-extensions/visual-design/style-selector.ts +177 -0
  26. package/augment-extensions/visual-design/types.ts +302 -0
  27. package/augment-extensions/visual-design/visual-design-core.ts +469 -0
  28. package/augment-extensions/workflows/adr-support/README.md +227 -0
  29. package/augment-extensions/workflows/adr-support/__tests__/adr-validator.test.ts +203 -0
  30. package/augment-extensions/workflows/adr-support/adr-validator.ts +162 -0
  31. package/augment-extensions/workflows/adr-support/examples/complete-lifecycle-example.md +449 -0
  32. package/augment-extensions/workflows/adr-support/examples/integration-example.md +580 -0
  33. package/augment-extensions/workflows/adr-support/examples/superseding-example.md +436 -0
  34. package/augment-extensions/workflows/adr-support/module.json +112 -0
  35. package/augment-extensions/workflows/adr-support/rules/adr-creation.md +372 -0
  36. package/augment-extensions/workflows/adr-support/rules/beads-integration.md +443 -0
  37. package/augment-extensions/workflows/adr-support/rules/conflict-detection.md +486 -0
  38. package/augment-extensions/workflows/adr-support/rules/decision-detection.md +362 -0
  39. package/augment-extensions/workflows/adr-support/rules/lifecycle-management.md +427 -0
  40. package/augment-extensions/workflows/adr-support/rules/openspec-integration.md +465 -0
  41. package/augment-extensions/workflows/adr-support/rules/template-selection.md +405 -0
  42. package/augment-extensions/workflows/adr-support/rules/validation-rules.md +543 -0
  43. package/augment-extensions/workflows/adr-support/schemas/adr-config.json +191 -0
  44. package/augment-extensions/workflows/adr-support/schemas/adr-metadata.json +172 -0
  45. package/augment-extensions/workflows/adr-support/templates/business-case.md +235 -0
  46. package/augment-extensions/workflows/adr-support/templates/madr-elaborate.md +197 -0
  47. package/augment-extensions/workflows/adr-support/templates/madr-simple.md +68 -0
  48. package/augment-extensions/workflows/adr-support/templates/nygard.md +84 -0
  49. package/cli/dist/utils/__tests__/adr-validator.example.d.ts +6 -0
  50. package/cli/dist/utils/__tests__/adr-validator.example.d.ts.map +1 -0
  51. package/cli/dist/utils/__tests__/adr-validator.example.js +148 -0
  52. package/cli/dist/utils/__tests__/adr-validator.example.js.map +1 -0
  53. package/cli/dist/utils/adr-validator.d.ts +65 -0
  54. package/cli/dist/utils/adr-validator.d.ts.map +1 -0
  55. package/cli/dist/utils/adr-validator.js +203 -0
  56. package/cli/dist/utils/adr-validator.js.map +1 -0
  57. package/package.json +1 -1
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Tests for ADR Validation Module
3
+ */
4
+
5
+ import { describe, it, expect } from '@jest/globals';
6
+ import {
7
+ ADR,
8
+ isValidISO8601,
9
+ validateMetadata,
10
+ validateOptionalFields,
11
+ validateADRReferences
12
+ } from '../adr-validator';
13
+
14
+ describe('ADR Validator', () => {
15
+ describe('isValidISO8601', () => {
16
+ it('should accept valid ISO 8601 dates', () => {
17
+ expect(isValidISO8601('2026-02-06')).toBe(true);
18
+ expect(isValidISO8601('2024-01-01')).toBe(true);
19
+ expect(isValidISO8601('2024-12-31')).toBe(true);
20
+ });
21
+
22
+ it('should reject invalid dates', () => {
23
+ expect(isValidISO8601('2024-02-30')).toBe(false); // Invalid day
24
+ expect(isValidISO8601('2024-13-01')).toBe(false); // Invalid month
25
+ expect(isValidISO8601('2024-00-01')).toBe(false); // Invalid month
26
+ expect(isValidISO8601('2024-01-32')).toBe(false); // Invalid day
27
+ expect(isValidISO8601('24-01-01')).toBe(false); // Wrong format
28
+ expect(isValidISO8601('2024/01/01')).toBe(false); // Wrong separator
29
+ expect(isValidISO8601('2024-1-1')).toBe(false); // Missing leading zeros
30
+ expect(isValidISO8601('not-a-date')).toBe(false);
31
+ expect(isValidISO8601('')).toBe(false);
32
+ });
33
+ });
34
+
35
+ describe('validateMetadata', () => {
36
+ it('should accept valid ADR metadata', () => {
37
+ const validADR: ADR = {
38
+ id: 'adr-0001',
39
+ title: 'Use PostgreSQL for Primary Database',
40
+ status: 'approved',
41
+ date: '2026-02-06',
42
+ deciders: ['Tech Lead', 'Database Architect']
43
+ };
44
+
45
+ const result = validateMetadata(validADR);
46
+ expect(result.valid).toBe(true);
47
+ expect(result.errors).toEqual([]);
48
+ });
49
+
50
+ it('should reject missing required fields', () => {
51
+ const invalidADR = {
52
+ id: 'adr-0001',
53
+ title: 'Test',
54
+ status: 'approved'
55
+ } as ADR;
56
+
57
+ const result = validateMetadata(invalidADR);
58
+ expect(result.valid).toBe(false);
59
+ expect(result.errors).toContain('Missing required field: date');
60
+ expect(result.errors).toContain('At least one decider must be specified');
61
+ });
62
+
63
+ it('should reject invalid ID format', () => {
64
+ const invalidADR: ADR = {
65
+ id: 'adr-1', // Should be adr-0001
66
+ title: 'Valid Title Here',
67
+ status: 'approved',
68
+ date: '2026-02-06',
69
+ deciders: ['Tech Lead']
70
+ };
71
+
72
+ const result = validateMetadata(invalidADR);
73
+ expect(result.valid).toBe(false);
74
+ expect(result.errors).toContain('Invalid ID format. Must be adr-NNNN (e.g., adr-0001)');
75
+ });
76
+
77
+ it('should reject invalid title length', () => {
78
+ const shortTitle: ADR = {
79
+ id: 'adr-0001',
80
+ title: 'Short', // Less than 10 characters
81
+ status: 'approved',
82
+ date: '2026-02-06',
83
+ deciders: ['Tech Lead']
84
+ };
85
+
86
+ const result = validateMetadata(shortTitle);
87
+ expect(result.valid).toBe(false);
88
+ expect(result.errors).toContain('Title must be 10-100 characters');
89
+ });
90
+
91
+ it('should reject invalid status', () => {
92
+ const invalidStatus: ADR = {
93
+ id: 'adr-0001',
94
+ title: 'Valid Title Here',
95
+ status: 'invalid-status',
96
+ date: '2026-02-06',
97
+ deciders: ['Tech Lead']
98
+ };
99
+
100
+ const result = validateMetadata(invalidStatus);
101
+ expect(result.valid).toBe(false);
102
+ expect(result.errors?.some(e => e.includes('Invalid status'))).toBe(true);
103
+ });
104
+
105
+ it('should reject invalid date format', () => {
106
+ const invalidDate: ADR = {
107
+ id: 'adr-0001',
108
+ title: 'Valid Title Here',
109
+ status: 'approved',
110
+ date: '2024-02-30', // Invalid date
111
+ deciders: ['Tech Lead']
112
+ };
113
+
114
+ const result = validateMetadata(invalidDate);
115
+ expect(result.valid).toBe(false);
116
+ expect(result.errors).toContain('Invalid date format. Must be ISO 8601 (YYYY-MM-DD)');
117
+ });
118
+ });
119
+
120
+ describe('validateOptionalFields', () => {
121
+ it('should accept valid optional fields', () => {
122
+ const adr: ADR = {
123
+ id: 'adr-0001',
124
+ title: 'Valid Title Here',
125
+ status: 'approved',
126
+ date: '2026-02-06',
127
+ deciders: ['Tech Lead'],
128
+ tags: ['database', 'postgresql'],
129
+ supersedes: ['adr-0002'],
130
+ superseded_by: 'adr-0003'
131
+ };
132
+
133
+ const result = validateOptionalFields(adr);
134
+ expect(result.valid).toBe(true);
135
+ expect(result.warnings).toEqual([]);
136
+ });
137
+
138
+ it('should warn about invalid supersedes format', () => {
139
+ const adr: ADR = {
140
+ id: 'adr-0001',
141
+ title: 'Valid Title Here',
142
+ status: 'approved',
143
+ date: '2026-02-06',
144
+ deciders: ['Tech Lead'],
145
+ supersedes: ['adr-1', 'invalid-id'] // Invalid formats
146
+ };
147
+
148
+ const result = validateOptionalFields(adr);
149
+ expect(result.valid).toBe(false);
150
+ expect(result.warnings?.some(w => w.includes('Invalid ADR ID in supersedes'))).toBe(true);
151
+ });
152
+ });
153
+
154
+ describe('validateADRReferences', () => {
155
+ const existingADRs: ADR[] = [
156
+ {
157
+ id: 'adr-0001',
158
+ title: 'First Decision',
159
+ status: 'approved',
160
+ date: '2026-01-01',
161
+ deciders: ['Tech Lead']
162
+ },
163
+ {
164
+ id: 'adr-0002',
165
+ title: 'Second Decision',
166
+ status: 'approved',
167
+ date: '2026-01-02',
168
+ deciders: ['Tech Lead']
169
+ }
170
+ ];
171
+
172
+ it('should warn when related_decisions references non-existent ADR', () => {
173
+ const adr: ADR = {
174
+ id: 'adr-0003',
175
+ title: 'Third Decision',
176
+ status: 'approved',
177
+ date: '2026-01-03',
178
+ deciders: ['Tech Lead'],
179
+ related_decisions: ['adr-0001', 'adr-9999'] // adr-9999 doesn't exist
180
+ };
181
+
182
+ const result = validateADRReferences(adr, existingADRs);
183
+ expect(result.valid).toBe(false);
184
+ expect(result.warnings).toContain('Related ADR does not exist: adr-9999');
185
+ });
186
+
187
+ it('should pass when all references exist', () => {
188
+ const adr: ADR = {
189
+ id: 'adr-0003',
190
+ title: 'Third Decision',
191
+ status: 'approved',
192
+ date: '2026-01-03',
193
+ deciders: ['Tech Lead'],
194
+ related_decisions: ['adr-0001', 'adr-0002']
195
+ };
196
+
197
+ const result = validateADRReferences(adr, existingADRs);
198
+ expect(result.valid).toBe(true);
199
+ expect(result.warnings).toEqual([]);
200
+ });
201
+ });
202
+ });
203
+
@@ -0,0 +1,162 @@
1
+ /**
2
+ * ADR Validation Module
3
+ * Implements validation rules from validation-rules.md
4
+ */
5
+
6
+ export interface ADR {
7
+ id: string;
8
+ title: string;
9
+ status: string;
10
+ date: string;
11
+ deciders: string[];
12
+ tags?: string[];
13
+ supersedes?: string[];
14
+ superseded_by?: string;
15
+ related_decisions?: string[];
16
+ related_specs?: string[];
17
+ related_tasks?: string[];
18
+ }
19
+
20
+ export interface ValidationResult {
21
+ valid: boolean;
22
+ errors?: string[];
23
+ warnings?: string[];
24
+ }
25
+
26
+ const VALID_STATUSES = ['draft', 'proposed', 'approved', 'implemented', 'maintained', 'superseded', 'sunset'];
27
+
28
+ /**
29
+ * Validate ISO 8601 date format (YYYY-MM-DD)
30
+ */
31
+ export function isValidISO8601(date: string): boolean {
32
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
33
+ return false;
34
+ }
35
+
36
+ const [year, month, day] = date.split('-').map(Number);
37
+
38
+ // Check basic ranges
39
+ if (month < 1 || month > 12 || day < 1 || day > 31) {
40
+ return false;
41
+ }
42
+
43
+ // Create date in UTC to avoid timezone issues
44
+ const d = new Date(Date.UTC(year, month - 1, day));
45
+
46
+ if (isNaN(d.getTime())) {
47
+ return false;
48
+ }
49
+
50
+ // Verify the date components match (handles invalid dates like 2024-02-30)
51
+ return d.getUTCFullYear() === year &&
52
+ d.getUTCMonth() === month - 1 &&
53
+ d.getUTCDate() === day;
54
+ }
55
+
56
+ /**
57
+ * Validate required metadata fields
58
+ */
59
+ export function validateMetadata(adr: ADR): ValidationResult {
60
+ const errors: string[] = [];
61
+
62
+ // ID validation
63
+ if (!adr.id) {
64
+ errors.push("Missing required field: id");
65
+ } else if (!/^adr-\d{4}$/.test(adr.id)) {
66
+ errors.push("Invalid ID format. Must be adr-NNNN (e.g., adr-0001)");
67
+ }
68
+
69
+ // Title validation
70
+ if (!adr.title) {
71
+ errors.push("Missing required field: title");
72
+ } else if (adr.title.length < 10 || adr.title.length > 100) {
73
+ errors.push("Title must be 10-100 characters");
74
+ }
75
+
76
+ // Status validation
77
+ if (!adr.status) {
78
+ errors.push("Missing required field: status");
79
+ } else if (!VALID_STATUSES.includes(adr.status)) {
80
+ errors.push(`Invalid status. Must be one of: ${VALID_STATUSES.join(', ')}`);
81
+ }
82
+
83
+ // Date validation
84
+ if (!adr.date) {
85
+ errors.push("Missing required field: date");
86
+ } else if (!isValidISO8601(adr.date)) {
87
+ errors.push("Invalid date format. Must be ISO 8601 (YYYY-MM-DD)");
88
+ }
89
+
90
+ // Deciders validation
91
+ if (!adr.deciders || adr.deciders.length === 0) {
92
+ errors.push("At least one decider must be specified");
93
+ }
94
+
95
+ return { valid: errors.length === 0, errors };
96
+ }
97
+
98
+ /**
99
+ * Validate optional fields
100
+ */
101
+ export function validateOptionalFields(adr: ADR): ValidationResult {
102
+ const warnings: string[] = [];
103
+
104
+ // Tags validation
105
+ if (adr.tags && !Array.isArray(adr.tags)) {
106
+ warnings.push("Tags must be an array");
107
+ }
108
+
109
+ // Supersedes validation
110
+ if (adr.supersedes) {
111
+ if (!Array.isArray(adr.supersedes)) {
112
+ warnings.push("Supersedes must be an array");
113
+ } else {
114
+ adr.supersedes.forEach(id => {
115
+ if (!/^adr-\d{4}$/.test(id)) {
116
+ warnings.push(`Invalid ADR ID in supersedes: ${id}`);
117
+ }
118
+ });
119
+ }
120
+ }
121
+
122
+ // Superseded_by validation
123
+ if (adr.superseded_by && !/^adr-\d{4}$/.test(adr.superseded_by)) {
124
+ warnings.push(`Invalid ADR ID in superseded_by: ${adr.superseded_by}`);
125
+ }
126
+
127
+ return { valid: warnings.length === 0, warnings };
128
+ }
129
+
130
+ /**
131
+ * Validate ADR references (related_decisions, supersedes, etc.)
132
+ */
133
+ export function validateADRReferences(adr: ADR, allADRs: ADR[]): ValidationResult {
134
+ const warnings: string[] = [];
135
+ const adrIds = new Set(allADRs.map(a => a.id));
136
+
137
+ // Validate supersedes references
138
+ if (adr.supersedes) {
139
+ adr.supersedes.forEach(id => {
140
+ if (!adrIds.has(id)) {
141
+ warnings.push(`Referenced ADR does not exist: ${id}`);
142
+ }
143
+ });
144
+ }
145
+
146
+ // Validate superseded_by reference
147
+ if (adr.superseded_by && !adrIds.has(adr.superseded_by)) {
148
+ warnings.push(`Referenced ADR does not exist: ${adr.superseded_by}`);
149
+ }
150
+
151
+ // Validate related_decisions
152
+ if (adr.related_decisions) {
153
+ adr.related_decisions.forEach(id => {
154
+ if (!adrIds.has(id)) {
155
+ warnings.push(`Related ADR does not exist: ${id}`);
156
+ }
157
+ });
158
+ }
159
+
160
+ return { valid: warnings.length === 0, warnings };
161
+ }
162
+