arcvision 0.2.24 → 0.2.25

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arcvision",
3
- "version": "0.2.24",
3
+ "version": "0.2.25",
4
4
  "description": "ArcVision CLI - Architectural Governance and Invariant Detection Tool",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -191,8 +191,9 @@ function buildContext(fileNodes, edges, symbols, options = {}) {
191
191
  architectural_boundaries: options.architecturalBoundaries || {},
192
192
  structural_invariants: options.structuralInvariants || [],
193
193
  // Include detected invariants from the current scan - these should conform to the schema specification
194
- invariants: Array.isArray(options.autoDetectedInvariants) ? options.autoDetectedInvariants :
195
- Array.isArray(options.detectedInvariants) ? options.detectedInvariants : [],
194
+ invariants: Array.isArray(options.autoDetectedInvariants) && options.autoDetectedInvariants.length > 0 ? options.autoDetectedInvariants :
195
+ Array.isArray(options.detectedInvariants) && options.detectedInvariants.length > 0 ? options.detectedInvariants :
196
+ [],
196
197
  // Include invariant analysis results
197
198
  invariant_analysis: options.invariantAnalysis || null,
198
199
  // Include architectural health assessment
@@ -133,6 +133,65 @@ async function scan(directory) {
133
133
  directory
134
134
  );
135
135
 
136
+ // Load existing invariants from arcvision.context.json (primary source)
137
+ const fs = require('fs');
138
+ const contextPath = path.join(directory, 'arcvision_context', 'arcvision.context.json');
139
+ let existingInvariants = [];
140
+
141
+ if (fs.existsSync(contextPath)) {
142
+ try {
143
+ const contextContent = fs.readFileSync(contextPath, 'utf8');
144
+ const contextData = JSON.parse(contextContent);
145
+ if (contextData.invariants && Array.isArray(contextData.invariants)) {
146
+ existingInvariants = contextData.invariants;
147
+ console.log(`\nšŸ’¾ Loaded ${existingInvariants.length} existing invariants from arcvision.context.json`);
148
+ }
149
+ } catch (error) {
150
+ console.warn(`āš ļø Could not load existing invariants from context: ${error.message}`);
151
+ }
152
+ }
153
+
154
+ // Also check legacy .arcvision/invariants.json for backward compatibility
155
+ const legacyInvariantsPath = path.join(directory, '.arcvision', 'invariants.json');
156
+ if (fs.existsSync(legacyInvariantsPath)) {
157
+ try {
158
+ const legacyContent = fs.readFileSync(legacyInvariantsPath, 'utf8');
159
+ const legacyData = JSON.parse(legacyContent);
160
+ let legacyInvariants = [];
161
+ if (Array.isArray(legacyData)) {
162
+ legacyInvariants = legacyData;
163
+ } else if (legacyData.project_specific_invariants && Array.isArray(legacyData.project_specific_invariants)) {
164
+ legacyInvariants = legacyData.project_specific_invariants;
165
+ }
166
+
167
+ if (legacyInvariants.length > 0) {
168
+ console.log(`\nšŸ’¾ Loaded ${legacyInvariants.length} legacy invariants from .arcvision/invariants.json`);
169
+ // Merge with existing invariants, avoiding duplicates
170
+ const existingIds = new Set(existingInvariants.map(inv => inv.id));
171
+ for (const legacyInv of legacyInvariants) {
172
+ if (!existingIds.has(legacyInv.id)) {
173
+ existingInvariants.push(legacyInv);
174
+ existingIds.add(legacyInv.id);
175
+ }
176
+ }
177
+ }
178
+ } catch (error) {
179
+ console.warn(`āš ļø Could not load legacy invariants: ${error.message}`);
180
+ }
181
+ }
182
+
183
+ // Combine detected invariants with existing ones, avoiding duplicates
184
+ const allInvariants = [...detectedInvariants];
185
+ const existingIds = new Set(detectedInvariants.map(inv => inv.id));
186
+ for (const existingInv of existingInvariants) {
187
+ if (!existingIds.has(existingInv.id)) {
188
+ allInvariants.push(existingInv);
189
+ existingIds.add(existingInv.id);
190
+ }
191
+ }
192
+
193
+ console.log(`šŸ“Š Total invariants to embed in context: ${allInvariants.length}`);
194
+
136
195
  // Only analyze if we found invariants
137
196
  let invariantAnalysis = null;
138
197
  let architecturalHealth = null;
@@ -210,6 +269,10 @@ async function scan(directory) {
210
269
  // Prepare context options without archetype initially
211
270
  const { archetype: originalArchetype, ...otherContextOptions } = contextOptions;
212
271
 
272
+ // Update the combined invariants in otherContextOptions before creating finalContextOptions
273
+ otherContextOptions.autoDetectedInvariants = allInvariants;
274
+ otherContextOptions.detectedInvariants = allInvariants;
275
+
213
276
  const finalContextOptions = {
214
277
  directory: directory,
215
278
  projectName: path.basename(directory),
@@ -268,6 +331,24 @@ async function scan(directory) {
268
331
  // Deterministic sort for consistent hashing/snapshots
269
332
  const sortedContext = sortContext(context);
270
333
 
334
+ // Ensure authority ledger is created in the arcvision_context directory
335
+ const arcvisionDir = path.join(directory, 'arcvision_context');
336
+ if (!fs.existsSync(arcvisionDir)) {
337
+ fs.mkdirSync(arcvisionDir, { recursive: true });
338
+ console.log('šŸ“ Created arcvision_context directory');
339
+ }
340
+
341
+ // Initialize authority ledger in the correct location
342
+ const { AuthorityLedger } = require('./authority-ledger');
343
+ const ledgerPath = path.join(arcvisionDir, 'architecture.authority.ledger.json');
344
+ const authorityLedger = new AuthorityLedger(ledgerPath);
345
+
346
+ // Ensure ledger file exists
347
+ if (!fs.existsSync(ledgerPath)) {
348
+ authorityLedger.initialize();
349
+ console.log('šŸ“ Created architecture.authority.ledger.json');
350
+ }
351
+
271
352
  console.log(' āœ… Context Verified & Ready');
272
353
 
273
354
  return sortedContext;
package/src/index.js CHANGED
@@ -721,11 +721,45 @@ program
721
721
  console.log(chalk.green(`āœ… Loaded ${loadedInvariants.length} auto-detected invariants from context file`));
722
722
  loadSuccess = loadedInvariants.length > 0;
723
723
  } else {
724
- console.log(chalk.yellow('No auto-detected invariants found in context file'));
724
+ console.log(chalk.yellow('No auto-detected invariants found in context file'));
725
+ // Check if invariants exist in the legacy location and migrate them to context
726
+ if (fs.existsSync(invariantsFile)) {
727
+ console.log(chalk.blue(`Found legacy invariants file at: ${invariantsFile}`));
728
+ const legacyInvariants = JSON.parse(fs.readFileSync(invariantsFile, 'utf8'));
729
+ if (Array.isArray(legacyInvariants)) {
730
+ for (const invariant of legacyInvariants) {
731
+ if (invariantRegistry.register(invariant)) {
732
+ loadedInvariants.push(invariant);
733
+ }
734
+ }
735
+ console.log(chalk.green(`āœ… Loaded ${legacyInvariants.length} invariants from legacy file`));
736
+ loadSuccess = loadedInvariants.length > 0;
737
+ }
738
+ }
725
739
  }
726
740
  } catch (contextError) {
727
741
  console.log(chalk.yellow(`āš ļø Could not load invariants from context file: ${contextError.message}`));
728
742
  }
743
+ } else {
744
+ console.log(chalk.yellow(`āš ļø Context file not found: ${contextFilePath}`));
745
+ // Try to load from legacy location if context file doesn't exist
746
+ if (fs.existsSync(invariantsFile)) {
747
+ console.log(chalk.blue(`Attempting to load invariants from legacy location: ${invariantsFile}`));
748
+ try {
749
+ const legacyInvariants = JSON.parse(fs.readFileSync(invariantsFile, 'utf8'));
750
+ if (Array.isArray(legacyInvariants)) {
751
+ for (const invariant of legacyInvariants) {
752
+ if (invariantRegistry.register(invariant)) {
753
+ loadedInvariants.push(invariant);
754
+ }
755
+ }
756
+ console.log(chalk.green(`āœ… Loaded ${legacyInvariants.length} invariants from legacy file`));
757
+ loadSuccess = loadedInvariants.length > 0;
758
+ }
759
+ } catch (legacyError) {
760
+ console.log(chalk.yellow(`āš ļø Could not load invariants from legacy file: ${legacyError.message}`));
761
+ }
762
+ }
729
763
  }
730
764
 
731
765
  // Then, try to load project-specific invariants from the separate file (for backward compatibility)