arcvision 0.2.25 → 0.2.26
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 +59 -0
- package/package.json +1 -1
- package/src/core/authority-ledger.js +18 -20
- package/src/core/change-evaluator.js +56 -53
- package/src/core/cli-validator.js +59 -61
- package/src/core/invariant-detector.js +123 -103
- package/src/core/override-handler.js +28 -23
- package/src/core/scanner.js +114 -74
- package/src/engine/pass4_signals.js +12 -40
- package/src/index.js +38 -91
package/src/index.js
CHANGED
|
@@ -695,103 +695,43 @@ program
|
|
|
695
695
|
|
|
696
696
|
console.log(chalk.green(`✅ Loaded context from: ${contextFile}`));
|
|
697
697
|
|
|
698
|
-
// Load invariants from
|
|
699
|
-
const invariantsFile = options.invariantsFile || path.join(targetDir, '.arcvision', 'invariants.json');
|
|
700
|
-
let loadSuccess = false;
|
|
698
|
+
// Load invariants strictly from the main context file (or explicit override)
|
|
701
699
|
let loadedInvariants = [];
|
|
700
|
+
if (context && context.invariants && Array.isArray(context.invariants)) {
|
|
701
|
+
console.log(chalk.blue(`Loading ${context.invariants.length} invariants from context file...`));
|
|
702
|
+
for (const invariant of context.invariants) {
|
|
703
|
+
if (invariantRegistry.register(invariant)) {
|
|
704
|
+
loadedInvariants.push(invariant);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
console.log(chalk.green(`✅ Loaded ${loadedInvariants.length} invariants from context file`));
|
|
708
|
+
} else {
|
|
709
|
+
console.log(chalk.yellow('No invariants found in context file'));
|
|
710
|
+
}
|
|
702
711
|
|
|
703
|
-
//
|
|
704
|
-
|
|
705
|
-
|
|
712
|
+
// If explicit invariants file provided, load it too
|
|
713
|
+
if (options.invariantsFile && fs.existsSync(options.invariantsFile)) {
|
|
714
|
+
console.log(chalk.blue(`Loading manual invariants from ${options.invariantsFile}...`));
|
|
706
715
|
try {
|
|
707
|
-
const
|
|
708
|
-
const
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
console.log(chalk.blue(`Loading ${contextData.invariants.length} auto-detected invariants from context file...`));
|
|
713
|
-
|
|
714
|
-
// Load each invariant individually to the registry
|
|
715
|
-
for (const invariant of contextData.invariants) {
|
|
716
|
+
const invContent = fs.readFileSync(options.invariantsFile, 'utf8');
|
|
717
|
+
const manualInvariants = JSON.parse(invContent);
|
|
718
|
+
if (Array.isArray(manualInvariants)) {
|
|
719
|
+
let manualCount = 0;
|
|
720
|
+
for (const invariant of manualInvariants) {
|
|
716
721
|
if (invariantRegistry.register(invariant)) {
|
|
717
722
|
loadedInvariants.push(invariant);
|
|
723
|
+
manualCount++;
|
|
718
724
|
}
|
|
719
725
|
}
|
|
720
|
-
|
|
721
|
-
console.log(chalk.green(`✅ Loaded ${loadedInvariants.length} auto-detected invariants from context file`));
|
|
722
|
-
loadSuccess = loadedInvariants.length > 0;
|
|
723
|
-
} else {
|
|
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
|
-
}
|
|
726
|
+
console.log(chalk.green(`✅ Loaded ${manualCount} additional invariants from ${options.invariantsFile}`));
|
|
739
727
|
}
|
|
740
|
-
} catch (
|
|
741
|
-
console.
|
|
728
|
+
} catch (err) {
|
|
729
|
+
console.warn(chalk.yellow(`⚠️ Could not load invariants from ${options.invariantsFile}: ${err.message}`));
|
|
742
730
|
}
|
|
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
|
-
}
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
// Then, try to load project-specific invariants from the separate file (for backward compatibility)
|
|
766
|
-
if (fs.existsSync(invariantsFile)) {
|
|
767
|
-
console.log(chalk.blue(`Attempting to load project-specific invariants from: ${invariantsFile}`));
|
|
768
|
-
// We'll load the separate file to supplement the context file invariants
|
|
769
|
-
const fileLoadSuccess = invariantRegistry.loadFromFile(invariantsFile);
|
|
770
|
-
if (fileLoadSuccess) {
|
|
771
|
-
const fileInvariants = invariantRegistry.getAll().filter(inv =>
|
|
772
|
-
!loadedInvariants.some(loaded => loaded.id === inv.id)
|
|
773
|
-
);
|
|
774
|
-
console.log(chalk.green(`✅ Loaded ${fileInvariants.length} project-specific invariants from: ${invariantsFile}`));
|
|
775
|
-
loadedInvariants = [...loadedInvariants, ...fileInvariants];
|
|
776
|
-
loadSuccess = true;
|
|
777
|
-
} else {
|
|
778
|
-
console.log(chalk.yellow(`⚠️ Failed to load project-specific invariants from: ${invariantsFile}`));
|
|
779
|
-
}
|
|
780
|
-
} else {
|
|
781
|
-
console.log(chalk.yellow(`⚠️ No project-specific invariants file found: ${invariantsFile}`));
|
|
782
731
|
}
|
|
783
732
|
|
|
784
|
-
//
|
|
785
|
-
|
|
786
|
-
if (loadedInvariants.length > 0) {
|
|
787
|
-
console.log(chalk.blue('📋 Loaded invariants:'));
|
|
788
|
-
loadedInvariants.forEach((inv, index) => {
|
|
789
|
-
console.log(chalk.blue(` ${index + 1}. ${inv.id} (${inv.severity}) - ${inv.description}`));
|
|
790
|
-
});
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
// If invariants couldn't be loaded or file doesn't exist, use defaults
|
|
794
|
-
if (!loadSuccess || loadedInvariants.length === 0) {
|
|
733
|
+
// If invariants couldn't be loaded, use defaults
|
|
734
|
+
if (loadedInvariants.length === 0) {
|
|
795
735
|
console.log(chalk.yellow('⚠️ No invariants loaded, using default invariants...'));
|
|
796
736
|
const defaultInvariants = JSON.parse(process.env.DEFAULT_INVARIANTS_JSON || JSON.stringify([
|
|
797
737
|
{
|
|
@@ -940,7 +880,12 @@ program
|
|
|
940
880
|
console.log(chalk.blue('🔐 Processing Authoritative Gate Override'));
|
|
941
881
|
console.log(chalk.blue('Creating permanent architectural scar...\n'));
|
|
942
882
|
|
|
943
|
-
const
|
|
883
|
+
const targetDir = path.resolve('.'); // Default to current directory
|
|
884
|
+
const ledgerPath = path.join(targetDir, 'arcvision_context', 'architecture.authority.ledger.json');
|
|
885
|
+
const { OverrideHandler } = require('./core/override-handler');
|
|
886
|
+
const handler = new OverrideHandler(ledgerPath);
|
|
887
|
+
|
|
888
|
+
const result = await handler.processOverride({
|
|
944
889
|
eventId: options.eventId,
|
|
945
890
|
reason: options.reason,
|
|
946
891
|
owner: options.owner,
|
|
@@ -974,14 +919,16 @@ program
|
|
|
974
919
|
// Add ledger inspection command
|
|
975
920
|
program
|
|
976
921
|
.command('ledger')
|
|
977
|
-
.
|
|
922
|
+
.argument('[directory]', 'Directory to inspect', '.')
|
|
978
923
|
.option('--stats', 'Show ledger statistics')
|
|
979
924
|
.option('--recent-blocks', 'Show recent unresolved BLOCKED events')
|
|
980
925
|
.option('--export <format>', 'Export ledger (json|csv)')
|
|
981
|
-
.action(async (options) => {
|
|
926
|
+
.action(async (directory, options) => {
|
|
982
927
|
try {
|
|
983
|
-
|
|
984
|
-
|
|
928
|
+
const targetDir = path.resolve(directory);
|
|
929
|
+
// Initialize Authority Ledger with targeted path
|
|
930
|
+
const ledgerPath = path.join(targetDir, 'arcvision_context', 'architecture.authority.ledger.json');
|
|
931
|
+
const authorityLedger = new AuthorityLedger(ledgerPath);
|
|
985
932
|
|
|
986
933
|
if (options.stats) {
|
|
987
934
|
const stats = authorityLedger.getStats();
|