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 +1 -1
- package/src/core/context_builder.js +3 -2
- package/src/core/scanner.js +81 -0
- package/src/index.js +35 -1
package/package.json
CHANGED
|
@@ -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
|
package/src/core/scanner.js
CHANGED
|
@@ -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)
|