arcvision 0.2.5 → 0.2.6
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 +85 -74
- package/dist/index.js +775 -8
- package/package.json +1 -1
- package/schema/arcvision_context_schema_v1.json +138 -1
- package/dist/schema/arcvision_context_schema_v1.json +0 -84
package/README.md
CHANGED
|
@@ -1,74 +1,85 @@
|
|
|
1
|
-
# ArcVision
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
##
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
- **
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
1
|
+
# ArcVision System Context Artifact
|
|
2
|
+
|
|
3
|
+
## What This Is
|
|
4
|
+
|
|
5
|
+
This file is the **canonical structural context** of this codebase.
|
|
6
|
+
It represents how the system actually works — not how it is described.
|
|
7
|
+
|
|
8
|
+
It is generated directly from source code by ArcVision.
|
|
9
|
+
|
|
10
|
+
## What This Replaces
|
|
11
|
+
|
|
12
|
+
This artifact replaces:
|
|
13
|
+
- Manual repository scanning
|
|
14
|
+
- Tribal knowledge held by senior engineers
|
|
15
|
+
- Re-explaining the system to new developers
|
|
16
|
+
- Re-prompting LLMs with partial or incorrect context
|
|
17
|
+
- Guessing blast radius of changes
|
|
18
|
+
|
|
19
|
+
## When You Must Use This
|
|
20
|
+
|
|
21
|
+
Use this artifact when:
|
|
22
|
+
- Onboarding a new developer
|
|
23
|
+
- Prompting an AI assistant about this codebase
|
|
24
|
+
- Making architectural changes
|
|
25
|
+
- Investigating unexpected behavior
|
|
26
|
+
- Assessing risk before modifying core modules
|
|
27
|
+
|
|
28
|
+
## What This Artifact Contains
|
|
29
|
+
|
|
30
|
+
- Canonical module and dependency graph
|
|
31
|
+
- Execution and data flow relationships
|
|
32
|
+
- Structural roles (service, store, boundary, etc.)
|
|
33
|
+
- Invariants inferred from the system
|
|
34
|
+
- Impact metrics (blast radius, coupling)
|
|
35
|
+
|
|
36
|
+
## Determinism & Trust
|
|
37
|
+
|
|
38
|
+
- Generated from commit: b63e62db4aedf6ffb21055dd88d13c8a947a7422
|
|
39
|
+
- Generation timestamp: 2026-01-13T03:50:34.571Z
|
|
40
|
+
- Tool version: 0.2.5
|
|
41
|
+
- Deterministic: same input → same output
|
|
42
|
+
- Explicit assumptions listed inside the artifact
|
|
43
|
+
|
|
44
|
+
If this artifact conflicts with human memory, **trust the artifact**.
|
|
45
|
+
|
|
46
|
+
## Structural Context Hubs
|
|
47
|
+
|
|
48
|
+
The following files have the highest blast radius and represent critical structural hubs in the system:
|
|
49
|
+
|
|
50
|
+
- **src/lib/utils.ts**
|
|
51
|
+
- Blast Radius: 62 files (14.73% of codebase)
|
|
52
|
+
- Risk: Changes here may silently propagate across the system.
|
|
53
|
+
|
|
54
|
+
- **src/components/ui/button.tsx**
|
|
55
|
+
- Blast Radius: 49 files (11.64% of codebase)
|
|
56
|
+
- Risk: Acts as a coordination layer between components.
|
|
57
|
+
|
|
58
|
+
- **src/lib/supabase/client.ts**
|
|
59
|
+
- Blast Radius: 45 files (10.69% of codebase)
|
|
60
|
+
- Risk: Modifications can cause widespread inconsistencies.
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
## How to Use With AI
|
|
65
|
+
|
|
66
|
+
When prompting AI tools, include this file as system context.
|
|
67
|
+
Do not ask the AI to infer architecture without it.
|
|
68
|
+
|
|
69
|
+
## When to Regenerate
|
|
70
|
+
|
|
71
|
+
Regenerate this artifact when:
|
|
72
|
+
- Core modules change
|
|
73
|
+
- New services are added
|
|
74
|
+
- Dependency structure shifts
|
|
75
|
+
|
|
76
|
+
Run:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
arcvision scan --upload
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Source of Truth
|
|
83
|
+
|
|
84
|
+
This artifact is the **source of truth** for system structure.
|
|
85
|
+
All explanations, decisions, and AI reasoning should reference it.
|
package/dist/index.js
CHANGED
|
@@ -57524,7 +57524,7 @@ var require_pass1_facts = __commonJS({
|
|
|
57524
57524
|
if (fs2.existsSync(pluginDir)) {
|
|
57525
57525
|
pluginManager.loadPluginsFromDirectory(pluginDir);
|
|
57526
57526
|
}
|
|
57527
|
-
const files = await glob("**/*.{js,jsx,ts,tsx,json}", {
|
|
57527
|
+
const files = await glob("**/*.{js,jsx,ts,tsx,json,lua}", {
|
|
57528
57528
|
...scanOptions,
|
|
57529
57529
|
ignore: [...scanOptions.ignore, "**/*.d.ts", "**/.next/**", "**/coverage/**", "**/arcvision.context.json"]
|
|
57530
57530
|
});
|
|
@@ -57545,14 +57545,27 @@ var require_pass1_facts = __commonJS({
|
|
|
57545
57545
|
isJson: true,
|
|
57546
57546
|
raw: content
|
|
57547
57547
|
};
|
|
57548
|
+
} else if (file.endsWith(".lua")) {
|
|
57549
|
+
const content = fs2.readFileSync(file, "utf-8");
|
|
57550
|
+
metadata = {
|
|
57551
|
+
id: file,
|
|
57552
|
+
isLua: true,
|
|
57553
|
+
raw: content,
|
|
57554
|
+
// Extract potential invocations from Lua content
|
|
57555
|
+
potentialInvocations: extractLuaInvocations(content)
|
|
57556
|
+
};
|
|
57548
57557
|
} else {
|
|
57549
57558
|
metadata = parser.parseFile(file);
|
|
57550
57559
|
}
|
|
57551
57560
|
metadata = await pluginManager.processFile(file, metadata);
|
|
57561
|
+
const isLuaFile = file.endsWith(".lua");
|
|
57562
|
+
const nodeType = isLuaFile ? "execution_script" : "file";
|
|
57563
|
+
const nodeRole = isLuaFile ? "atomic_redis_operation" : "Structure";
|
|
57552
57564
|
const node = {
|
|
57553
57565
|
id: normalizedRelativePath,
|
|
57554
57566
|
filePath: file,
|
|
57555
|
-
type:
|
|
57567
|
+
type: nodeType,
|
|
57568
|
+
role: nodeRole,
|
|
57556
57569
|
facts: {
|
|
57557
57570
|
imports: metadata.imports || [],
|
|
57558
57571
|
exports: metadata.exports || [],
|
|
@@ -57574,9 +57587,14 @@ var require_pass1_facts = __commonJS({
|
|
|
57574
57587
|
hooks: metadata.hookDependencies || [],
|
|
57575
57588
|
context: metadata.contextUsages || []
|
|
57576
57589
|
},
|
|
57577
|
-
react: metadata.componentUsage || []
|
|
57590
|
+
react: metadata.componentUsage || [],
|
|
57591
|
+
potentialInvocations: metadata.potentialInvocations || []
|
|
57578
57592
|
}
|
|
57579
57593
|
};
|
|
57594
|
+
if (isLuaFile) {
|
|
57595
|
+
node.language = "lua";
|
|
57596
|
+
node.execution_boundary = "redis";
|
|
57597
|
+
}
|
|
57580
57598
|
return { node, factCount: (metadata.imports?.length || 0) + (metadata.functionCalls?.length || 0) };
|
|
57581
57599
|
} catch (e) {
|
|
57582
57600
|
console.warn(`\u26A0\uFE0F Pass 1 failed for ${file}: ${e.message}`);
|
|
@@ -57596,6 +57614,22 @@ var require_pass1_facts = __commonJS({
|
|
|
57596
57614
|
console.log(` \u2713 Extracted ${totalFacts} raw syntactic facts`);
|
|
57597
57615
|
return rawNodes;
|
|
57598
57616
|
}
|
|
57617
|
+
function extractLuaInvocations(content) {
|
|
57618
|
+
const invocations = [];
|
|
57619
|
+
const patterns = [
|
|
57620
|
+
/readFileSync\(['"].*\.lua['"].*\)/gi,
|
|
57621
|
+
/defineCommand\(\s*\{\s*lua\s*:.*\}/gi,
|
|
57622
|
+
/redis\.call\(['"].*['"].*\)/gi,
|
|
57623
|
+
/redis\.pcall\(['"].*['"].*\)/gi
|
|
57624
|
+
];
|
|
57625
|
+
patterns.forEach((pattern) => {
|
|
57626
|
+
let match;
|
|
57627
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
57628
|
+
invocations.push(match[0]);
|
|
57629
|
+
}
|
|
57630
|
+
});
|
|
57631
|
+
return invocations;
|
|
57632
|
+
}
|
|
57599
57633
|
module2.exports = { executePass1 };
|
|
57600
57634
|
}
|
|
57601
57635
|
});
|
|
@@ -58165,6 +58199,66 @@ var require_pass2_semantics = __commonJS({
|
|
|
58165
58199
|
}
|
|
58166
58200
|
}
|
|
58167
58201
|
console.log(` \u2713 Resolved ${resolvedCalls} semantic call edges`);
|
|
58202
|
+
let luaInvocationCount = 0;
|
|
58203
|
+
for (const node of rawNodes) {
|
|
58204
|
+
if (!node.facts.potentialInvocations || node.facts.potentialInvocations.length === 0)
|
|
58205
|
+
continue;
|
|
58206
|
+
const content = node.filePath && require("fs").readFileSync(node.filePath, "utf-8");
|
|
58207
|
+
if (!content)
|
|
58208
|
+
continue;
|
|
58209
|
+
const luaInvocationPatterns = [
|
|
58210
|
+
/readFileSync\(['"].*\.lua['"].*\)/gi,
|
|
58211
|
+
/defineCommand\(\s*\{\s*lua\s*:.*?\}/gi,
|
|
58212
|
+
/require\(['"].*\.lua['"].*\)/gi,
|
|
58213
|
+
/fs\.readFileSync\(['"].*\.lua['"].*\)/gi,
|
|
58214
|
+
/import\s+.*?from\s+['"].*\.lua['"].*\)?/gi,
|
|
58215
|
+
/import\(['"].*\.lua['"].*\)/gi,
|
|
58216
|
+
/loadScript\(['"].*\.lua['"].*\)/gi,
|
|
58217
|
+
/loadLua\(['"].*\.lua['"].*\)/gi,
|
|
58218
|
+
/load\(['"].*\.lua['"].*\)/gi
|
|
58219
|
+
];
|
|
58220
|
+
for (const pattern of luaInvocationPatterns) {
|
|
58221
|
+
let match;
|
|
58222
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
58223
|
+
const luaFileMatch = match[0].match(/['"].*?\.lua['"]/);
|
|
58224
|
+
if (luaFileMatch) {
|
|
58225
|
+
let luaFilePath = luaFileMatch[0].slice(1, -1);
|
|
58226
|
+
if (luaFilePath.startsWith("./") || luaFilePath.startsWith("../")) {
|
|
58227
|
+
luaFilePath = path2.resolve(path2.dirname(node.filePath), luaFilePath);
|
|
58228
|
+
luaFilePath = normalize(path2.relative(rootDir, luaFilePath));
|
|
58229
|
+
} else if (luaFilePath.startsWith("/")) {
|
|
58230
|
+
luaFilePath = normalize(path2.relative(rootDir, path2.join(rootDir, luaFilePath)));
|
|
58231
|
+
} else {
|
|
58232
|
+
const commonLuaDirs = ["src", "scripts", "commands", "lua", "lib"];
|
|
58233
|
+
let foundPath = null;
|
|
58234
|
+
for (const dir of commonLuaDirs) {
|
|
58235
|
+
const candidatePath = normalize(path2.join(dir, luaFilePath));
|
|
58236
|
+
if (fileSet.has(candidatePath)) {
|
|
58237
|
+
foundPath = candidatePath;
|
|
58238
|
+
break;
|
|
58239
|
+
}
|
|
58240
|
+
}
|
|
58241
|
+
if (foundPath) {
|
|
58242
|
+
luaFilePath = foundPath;
|
|
58243
|
+
} else {
|
|
58244
|
+
const nodeDir = path2.dirname(node.id);
|
|
58245
|
+
luaFilePath = normalize(path2.join(nodeDir, luaFilePath));
|
|
58246
|
+
}
|
|
58247
|
+
}
|
|
58248
|
+
if (fileSet.has(luaFilePath)) {
|
|
58249
|
+
addEdge(node.id, luaFilePath, "invokes_execution_script", 1, {
|
|
58250
|
+
type: "lua_invocation",
|
|
58251
|
+
invocation_pattern: match[0],
|
|
58252
|
+
original_match: match[0],
|
|
58253
|
+
resolved_path: luaFilePath
|
|
58254
|
+
});
|
|
58255
|
+
luaInvocationCount++;
|
|
58256
|
+
}
|
|
58257
|
+
}
|
|
58258
|
+
}
|
|
58259
|
+
}
|
|
58260
|
+
}
|
|
58261
|
+
console.log(` \u2713 Detected ${luaInvocationCount} Lua script invocations`);
|
|
58168
58262
|
let typeEdgesCount = 0;
|
|
58169
58263
|
for (const node of rawNodes) {
|
|
58170
58264
|
if (!node.facts.typeAnalysis)
|
|
@@ -58522,6 +58616,8 @@ var require_id_generator = __commonJS({
|
|
|
58522
58616
|
var require_context_builder = __commonJS({
|
|
58523
58617
|
"src/core/context_builder.js"(exports2, module2) {
|
|
58524
58618
|
var path2 = require("path");
|
|
58619
|
+
var { spawnSync } = require("child_process");
|
|
58620
|
+
var crypto = require("crypto");
|
|
58525
58621
|
var { stableId } = require_id_generator();
|
|
58526
58622
|
function buildContext(fileNodes, edges, symbols, options = {}) {
|
|
58527
58623
|
const {
|
|
@@ -58619,9 +58715,11 @@ var require_context_builder = __commonJS({
|
|
|
58619
58715
|
total_dependencies: schemaEdges.length,
|
|
58620
58716
|
files_with_high_blast_radius: nodes.filter((n) => n.blast_radius > 5).length
|
|
58621
58717
|
};
|
|
58718
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
58719
|
+
const dateOnly = timestamp.split("T")[0];
|
|
58622
58720
|
const context = {
|
|
58623
58721
|
schema_version: "1.0.0",
|
|
58624
|
-
generated_at:
|
|
58722
|
+
generated_at: timestamp,
|
|
58625
58723
|
system: {
|
|
58626
58724
|
name: projectName,
|
|
58627
58725
|
root_path: path2.resolve(directory),
|
|
@@ -58631,11 +58729,453 @@ var require_context_builder = __commonJS({
|
|
|
58631
58729
|
edges: schemaEdges,
|
|
58632
58730
|
symbols: symbols || [],
|
|
58633
58731
|
metrics,
|
|
58634
|
-
contextSurface: options.contextSurface || []
|
|
58732
|
+
contextSurface: options.contextSurface || [],
|
|
58733
|
+
// Phase 2 requirement: Explicit Assumptions Section
|
|
58734
|
+
assumptions: generateAssumptions(),
|
|
58735
|
+
// Phase 2 requirement: Embed Commit Identity
|
|
58736
|
+
source: {
|
|
58737
|
+
repo: getGitInfo().repo,
|
|
58738
|
+
commit: getGitInfo().commit,
|
|
58739
|
+
generated_at: dateOnly,
|
|
58740
|
+
// Use date only to avoid time variations
|
|
58741
|
+
arcvision_version: options.arcvisionVersion || "0.1.0"
|
|
58742
|
+
},
|
|
58743
|
+
// Phase 3 requirement: Structural layers definition
|
|
58744
|
+
structural_layers: generateAdaptiveStructuralLayers(directory),
|
|
58745
|
+
// Phase 3 requirement: Project envelope
|
|
58746
|
+
project_envelope: generateProjectEnvelope(directory)
|
|
58747
|
+
};
|
|
58748
|
+
const contextWithoutIntegrity = { ...context };
|
|
58749
|
+
delete contextWithoutIntegrity.integrity;
|
|
58750
|
+
const hash = crypto.createHash("sha256").update(JSON.stringify(contextWithoutIntegrity)).digest("hex");
|
|
58751
|
+
context.integrity = {
|
|
58752
|
+
sha256: hash
|
|
58635
58753
|
};
|
|
58636
58754
|
return context;
|
|
58637
58755
|
}
|
|
58638
|
-
|
|
58756
|
+
function getGitInfo() {
|
|
58757
|
+
try {
|
|
58758
|
+
const originResult = spawnSync("git", ["remote", "get-url", "origin"], {
|
|
58759
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
58760
|
+
});
|
|
58761
|
+
let repoUrl = "unknown";
|
|
58762
|
+
if (originResult.status === 0) {
|
|
58763
|
+
let url = originResult.stdout.toString().trim();
|
|
58764
|
+
if (url.startsWith("git@")) {
|
|
58765
|
+
url = url.replace(/^git@(.*?):/, "https://$1/");
|
|
58766
|
+
url = url.replace(/\.git$/, "");
|
|
58767
|
+
} else if (url.endsWith(".git")) {
|
|
58768
|
+
url = url.replace(/\.git$/, "");
|
|
58769
|
+
}
|
|
58770
|
+
repoUrl = url;
|
|
58771
|
+
}
|
|
58772
|
+
const commitResult = spawnSync("git", ["rev-parse", "HEAD"], {
|
|
58773
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
58774
|
+
});
|
|
58775
|
+
let commitHash = "unknown";
|
|
58776
|
+
if (commitResult.status === 0) {
|
|
58777
|
+
commitHash = commitResult.stdout.toString().trim();
|
|
58778
|
+
}
|
|
58779
|
+
return {
|
|
58780
|
+
repo: repoUrl,
|
|
58781
|
+
commit: commitHash
|
|
58782
|
+
};
|
|
58783
|
+
} catch (error) {
|
|
58784
|
+
return {
|
|
58785
|
+
repo: "unknown",
|
|
58786
|
+
commit: "unknown"
|
|
58787
|
+
};
|
|
58788
|
+
}
|
|
58789
|
+
}
|
|
58790
|
+
function calculateIntegrityHash(obj) {
|
|
58791
|
+
try {
|
|
58792
|
+
const objCopy = JSON.parse(JSON.stringify(obj));
|
|
58793
|
+
if (objCopy.integrity) {
|
|
58794
|
+
delete objCopy.integrity;
|
|
58795
|
+
}
|
|
58796
|
+
const jsonString = JSON.stringify(objCopy);
|
|
58797
|
+
return crypto.createHash("sha256").update(jsonString).digest("hex");
|
|
58798
|
+
} catch (error) {
|
|
58799
|
+
return "calculation_error";
|
|
58800
|
+
}
|
|
58801
|
+
}
|
|
58802
|
+
function generateStructuralLayers() {
|
|
58803
|
+
return {
|
|
58804
|
+
"runtime_code": {
|
|
58805
|
+
"status": "included",
|
|
58806
|
+
"description": "Source files that directly participate in runtime execution and system behavior"
|
|
58807
|
+
},
|
|
58808
|
+
"execution_scripts": {
|
|
58809
|
+
"status": "included",
|
|
58810
|
+
"description": "Scripts invoked by runtime code to perform atomic or system-critical operations"
|
|
58811
|
+
},
|
|
58812
|
+
"infrastructure_scripts": {
|
|
58813
|
+
"status": "included",
|
|
58814
|
+
"description": "Scripts that manage infrastructure-level behavior (queues, databases, orchestration)"
|
|
58815
|
+
},
|
|
58816
|
+
"configuration": {
|
|
58817
|
+
"status": "optional",
|
|
58818
|
+
"description": "Project configuration files represented as metadata, not execution graph nodes"
|
|
58819
|
+
},
|
|
58820
|
+
"documentation": {
|
|
58821
|
+
"status": "optional",
|
|
58822
|
+
"description": "Documentation files represented as metadata only"
|
|
58823
|
+
},
|
|
58824
|
+
"assets": {
|
|
58825
|
+
"status": "excluded",
|
|
58826
|
+
"description": "Static assets with no effect on execution semantics"
|
|
58827
|
+
}
|
|
58828
|
+
};
|
|
58829
|
+
}
|
|
58830
|
+
function generateAdaptiveStructuralLayers(directory) {
|
|
58831
|
+
const fs2 = require("fs");
|
|
58832
|
+
const path3 = require("path");
|
|
58833
|
+
const hasPackageJson = fs2.existsSync(path3.join(directory, "package.json"));
|
|
58834
|
+
const hasConfigFiles = fs2.existsSync(path3.join(directory, "tsconfig.json")) || fs2.existsSync(path3.join(directory, "config")) || fs2.existsSync(path3.join(directory, "webpack.config.js"));
|
|
58835
|
+
const hasSrcDir = fs2.existsSync(path3.join(directory, "src"));
|
|
58836
|
+
const hasTestDir = fs2.existsSync(path3.join(directory, "test")) || fs2.existsSync(path3.join(directory, "tests"));
|
|
58837
|
+
const hasDocsDir = fs2.existsSync(path3.join(directory, "docs"));
|
|
58838
|
+
let totalFiles = 0;
|
|
58839
|
+
let jsFiles = 0;
|
|
58840
|
+
let tsFiles = 0;
|
|
58841
|
+
let luaFiles = 0;
|
|
58842
|
+
let configFiles = 0;
|
|
58843
|
+
function walk(dir, depth = 0) {
|
|
58844
|
+
if (depth > 3)
|
|
58845
|
+
return;
|
|
58846
|
+
if (!fs2.existsSync(dir))
|
|
58847
|
+
return;
|
|
58848
|
+
const items = fs2.readdirSync(dir, { withFileTypes: true });
|
|
58849
|
+
for (const item of items) {
|
|
58850
|
+
const fullPath = path3.join(dir, item.name);
|
|
58851
|
+
if (item.isDirectory()) {
|
|
58852
|
+
if (!item.name.startsWith(".") && item.name !== "node_modules" && item.name !== "dist" && item.name !== "build" && item.name !== ".git") {
|
|
58853
|
+
walk(fullPath, depth + 1);
|
|
58854
|
+
}
|
|
58855
|
+
} else {
|
|
58856
|
+
totalFiles++;
|
|
58857
|
+
if (item.name.endsWith(".js"))
|
|
58858
|
+
jsFiles++;
|
|
58859
|
+
if (item.name.endsWith(".ts"))
|
|
58860
|
+
tsFiles++;
|
|
58861
|
+
if (item.name.endsWith(".lua"))
|
|
58862
|
+
luaFiles++;
|
|
58863
|
+
if ([".json", ".yaml", ".yml", ".toml", ".config.js", ".config.ts", ".rc"].some((ext) => item.name.endsWith(ext)))
|
|
58864
|
+
configFiles++;
|
|
58865
|
+
}
|
|
58866
|
+
}
|
|
58867
|
+
}
|
|
58868
|
+
walk(directory);
|
|
58869
|
+
const isLuaProject = luaFiles > 0 && luaFiles / totalFiles > 0.1;
|
|
58870
|
+
const isLargeProject = totalFiles > 1e3;
|
|
58871
|
+
const layers = {
|
|
58872
|
+
"runtime_code": {
|
|
58873
|
+
"status": "included",
|
|
58874
|
+
"description": "Source files that directly participate in runtime execution and system behavior",
|
|
58875
|
+
"project_characteristics": {
|
|
58876
|
+
"has_package_json": hasPackageJson,
|
|
58877
|
+
"has_src_directory": hasSrcDir,
|
|
58878
|
+
"total_files": totalFiles,
|
|
58879
|
+
"javascript_files": jsFiles,
|
|
58880
|
+
"typescript_files": tsFiles,
|
|
58881
|
+
"lua_files": luaFiles
|
|
58882
|
+
}
|
|
58883
|
+
},
|
|
58884
|
+
"execution_scripts": {
|
|
58885
|
+
"status": isLuaProject ? "included" : "included",
|
|
58886
|
+
"description": "Scripts invoked by runtime code to perform atomic or system-critical operations",
|
|
58887
|
+
"project_characteristics": {
|
|
58888
|
+
"lua_files_count": luaFiles,
|
|
58889
|
+
"is_lua_project": isLuaProject
|
|
58890
|
+
}
|
|
58891
|
+
},
|
|
58892
|
+
"infrastructure_scripts": {
|
|
58893
|
+
"status": "included",
|
|
58894
|
+
"description": "Scripts that manage infrastructure-level behavior (queues, databases, orchestration)"
|
|
58895
|
+
},
|
|
58896
|
+
"configuration": {
|
|
58897
|
+
"status": hasConfigFiles ? "optional" : "excluded",
|
|
58898
|
+
"description": "Project configuration files represented as metadata, not execution graph nodes"
|
|
58899
|
+
},
|
|
58900
|
+
"documentation": {
|
|
58901
|
+
"status": hasDocsDir || hasPackageJson ? "optional" : "excluded",
|
|
58902
|
+
"description": "Documentation files represented as metadata only"
|
|
58903
|
+
},
|
|
58904
|
+
"assets": {
|
|
58905
|
+
"status": "excluded",
|
|
58906
|
+
"description": "Static assets with no effect on execution semantics"
|
|
58907
|
+
}
|
|
58908
|
+
};
|
|
58909
|
+
layers.project_metadata = {
|
|
58910
|
+
"size_category": isLargeProject ? "large" : totalFiles > 100 ? "medium" : "small",
|
|
58911
|
+
"file_count": totalFiles,
|
|
58912
|
+
"language_mix": {
|
|
58913
|
+
"javascript": jsFiles,
|
|
58914
|
+
"typescript": tsFiles,
|
|
58915
|
+
"lua": luaFiles,
|
|
58916
|
+
"config": configFiles
|
|
58917
|
+
},
|
|
58918
|
+
"has_package_management": hasPackageJson,
|
|
58919
|
+
"has_standard_structure": hasSrcDir,
|
|
58920
|
+
"has_tests": hasTestDir,
|
|
58921
|
+
"is_lua_intensive": isLuaProject
|
|
58922
|
+
};
|
|
58923
|
+
return layers;
|
|
58924
|
+
}
|
|
58925
|
+
function generateProjectEnvelope(directory) {
|
|
58926
|
+
const fs2 = require("fs");
|
|
58927
|
+
const path3 = require("path");
|
|
58928
|
+
const envelope = {
|
|
58929
|
+
configuration_files: [],
|
|
58930
|
+
documentation: [],
|
|
58931
|
+
build_tools: []
|
|
58932
|
+
};
|
|
58933
|
+
const configFiles = [
|
|
58934
|
+
"package.json",
|
|
58935
|
+
"tsconfig.json",
|
|
58936
|
+
"jsconfig.json",
|
|
58937
|
+
"webpack.config.js",
|
|
58938
|
+
"webpack.config.ts",
|
|
58939
|
+
"vite.config.js",
|
|
58940
|
+
"vite.config.ts",
|
|
58941
|
+
"rollup.config.js",
|
|
58942
|
+
"rollup.config.ts",
|
|
58943
|
+
"babel.config.js",
|
|
58944
|
+
"babel.config.ts",
|
|
58945
|
+
".babelrc",
|
|
58946
|
+
".babelrc.js",
|
|
58947
|
+
"eslint.config.mjs",
|
|
58948
|
+
"eslint.config.js",
|
|
58949
|
+
".eslintrc",
|
|
58950
|
+
".eslintrc.js",
|
|
58951
|
+
".eslintrc.json",
|
|
58952
|
+
"jest.config.js",
|
|
58953
|
+
"jest.config.ts",
|
|
58954
|
+
"jest.config.json",
|
|
58955
|
+
"mocha.opts",
|
|
58956
|
+
"nodemon.json",
|
|
58957
|
+
"nodemon.js",
|
|
58958
|
+
"next.config.ts",
|
|
58959
|
+
"next.config.js",
|
|
58960
|
+
"nuxt.config.js",
|
|
58961
|
+
"nuxt.config.ts",
|
|
58962
|
+
"postcss.config.mjs",
|
|
58963
|
+
"postcss.config.js",
|
|
58964
|
+
"tailwind.config.js",
|
|
58965
|
+
"tailwind.config.ts",
|
|
58966
|
+
"supabase/config.toml",
|
|
58967
|
+
"pnpm-workspace.yaml",
|
|
58968
|
+
"yarn.lock",
|
|
58969
|
+
"package-lock.json",
|
|
58970
|
+
"tsconfig.base.json",
|
|
58971
|
+
"tsconfig.node.json",
|
|
58972
|
+
"tsconfig.app.json",
|
|
58973
|
+
"turbo.json",
|
|
58974
|
+
"biome.json",
|
|
58975
|
+
"biome.jsonc",
|
|
58976
|
+
"angular.json",
|
|
58977
|
+
"nest-cli.json",
|
|
58978
|
+
"remix.config.js",
|
|
58979
|
+
"remix.config.ts"
|
|
58980
|
+
];
|
|
58981
|
+
const docFiles = [
|
|
58982
|
+
"README.md",
|
|
58983
|
+
"README.txt",
|
|
58984
|
+
"readme.md",
|
|
58985
|
+
"Readme.md",
|
|
58986
|
+
"CHANGELOG.md",
|
|
58987
|
+
"CHANGELOG.txt",
|
|
58988
|
+
"LICENSE",
|
|
58989
|
+
"LICENSE.md",
|
|
58990
|
+
"CONTRIBUTING.md",
|
|
58991
|
+
"NOTICE",
|
|
58992
|
+
"NOTICE.md",
|
|
58993
|
+
"SECURITY.md",
|
|
58994
|
+
"CODE_OF_CONDUCT.md",
|
|
58995
|
+
"PULL_REQUEST_TEMPLATE.md",
|
|
58996
|
+
"ISSUE_TEMPLATE.md",
|
|
58997
|
+
"HISTORY.md",
|
|
58998
|
+
"AUTHORS",
|
|
58999
|
+
"THANKS",
|
|
59000
|
+
"CITATION.cff",
|
|
59001
|
+
"CITATION.bib"
|
|
59002
|
+
];
|
|
59003
|
+
const buildToolFiles = [
|
|
59004
|
+
"typedoc.config.cjs",
|
|
59005
|
+
"typedoc.json",
|
|
59006
|
+
"typedoc.config.js",
|
|
59007
|
+
"typedoc.config.ts",
|
|
59008
|
+
"documentation.config.js",
|
|
59009
|
+
"docs.config.js",
|
|
59010
|
+
"api-extractor.json",
|
|
59011
|
+
"api-documenter.json",
|
|
59012
|
+
"jsdoc.json",
|
|
59013
|
+
"jsdoc.config.json",
|
|
59014
|
+
"compodoc.json",
|
|
59015
|
+
"documentation.yml"
|
|
59016
|
+
];
|
|
59017
|
+
function findFilesRecursively(dir, fileNames, results, maxDepth = 3, currentDepth = 0) {
|
|
59018
|
+
if (currentDepth > maxDepth)
|
|
59019
|
+
return;
|
|
59020
|
+
if (!fs2.existsSync(dir))
|
|
59021
|
+
return;
|
|
59022
|
+
const items = fs2.readdirSync(dir, { withFileTypes: true });
|
|
59023
|
+
for (const item of items) {
|
|
59024
|
+
const fullPath = path3.join(dir, item.name);
|
|
59025
|
+
if (item.isDirectory()) {
|
|
59026
|
+
if (!item.name.startsWith(".") && item.name !== "node_modules" && item.name !== "dist" && item.name !== "build") {
|
|
59027
|
+
findFilesRecursively(fullPath, fileNames, results, maxDepth, currentDepth + 1);
|
|
59028
|
+
}
|
|
59029
|
+
} else {
|
|
59030
|
+
if (fileNames.includes(item.name)) {
|
|
59031
|
+
const relativePath = path3.relative(directory, fullPath);
|
|
59032
|
+
results.push({
|
|
59033
|
+
path: relativePath,
|
|
59034
|
+
name: item.name
|
|
59035
|
+
});
|
|
59036
|
+
}
|
|
59037
|
+
}
|
|
59038
|
+
}
|
|
59039
|
+
}
|
|
59040
|
+
const foundConfigFiles = [];
|
|
59041
|
+
findFilesRecursively(directory, configFiles, foundConfigFiles);
|
|
59042
|
+
foundConfigFiles.forEach((fileObj) => {
|
|
59043
|
+
envelope.configuration_files.push({
|
|
59044
|
+
path: fileObj.path,
|
|
59045
|
+
role: getRoleForConfigFile(fileObj.name)
|
|
59046
|
+
});
|
|
59047
|
+
});
|
|
59048
|
+
const foundDocFiles = [];
|
|
59049
|
+
findFilesRecursively(directory, docFiles, foundDocFiles);
|
|
59050
|
+
foundDocFiles.forEach((fileObj) => {
|
|
59051
|
+
envelope.documentation.push({
|
|
59052
|
+
path: fileObj.path,
|
|
59053
|
+
role: getRoleForDocFile(fileObj.name)
|
|
59054
|
+
});
|
|
59055
|
+
});
|
|
59056
|
+
const foundBuildToolFiles = [];
|
|
59057
|
+
findFilesRecursively(directory, buildToolFiles, foundBuildToolFiles);
|
|
59058
|
+
foundBuildToolFiles.forEach((fileObj) => {
|
|
59059
|
+
envelope.build_tools.push({
|
|
59060
|
+
path: fileObj.path,
|
|
59061
|
+
role: getRoleForBuildToolFile(fileObj.name)
|
|
59062
|
+
});
|
|
59063
|
+
});
|
|
59064
|
+
envelope.configuration_files = envelope.configuration_files.filter(
|
|
59065
|
+
(file, index, self2) => index === self2.findIndex((f) => f.path === file.path)
|
|
59066
|
+
);
|
|
59067
|
+
envelope.documentation = envelope.documentation.filter(
|
|
59068
|
+
(file, index, self2) => index === self2.findIndex((f) => f.path === file.path)
|
|
59069
|
+
);
|
|
59070
|
+
envelope.build_tools = envelope.build_tools.filter(
|
|
59071
|
+
(file, index, self2) => index === self2.findIndex((f) => f.path === file.path)
|
|
59072
|
+
);
|
|
59073
|
+
return envelope;
|
|
59074
|
+
}
|
|
59075
|
+
function getRoleForConfigFile(fileName) {
|
|
59076
|
+
const roles = {
|
|
59077
|
+
"package.json": "dependency_manifest",
|
|
59078
|
+
"tsconfig.json": "compiler_configuration",
|
|
59079
|
+
"jsconfig.json": "compiler_configuration",
|
|
59080
|
+
"webpack.config.js": "bundler_configuration",
|
|
59081
|
+
"webpack.config.ts": "bundler_configuration",
|
|
59082
|
+
"vite.config.js": "bundler_configuration",
|
|
59083
|
+
"vite.config.ts": "bundler_configuration",
|
|
59084
|
+
"rollup.config.js": "bundler_configuration",
|
|
59085
|
+
"rollup.config.ts": "bundler_configuration",
|
|
59086
|
+
"babel.config.js": "transpiler_configuration",
|
|
59087
|
+
"babel.config.ts": "transpiler_configuration",
|
|
59088
|
+
".babelrc": "transpiler_configuration",
|
|
59089
|
+
".babelrc.js": "transpiler_configuration",
|
|
59090
|
+
"eslint.config.mjs": "linting_configuration",
|
|
59091
|
+
"eslint.config.js": "linting_configuration",
|
|
59092
|
+
".eslintrc": "linting_configuration",
|
|
59093
|
+
".eslintrc.js": "linting_configuration",
|
|
59094
|
+
".eslintrc.json": "linting_configuration",
|
|
59095
|
+
"jest.config.js": "testing_configuration",
|
|
59096
|
+
"jest.config.ts": "testing_configuration",
|
|
59097
|
+
"jest.config.json": "testing_configuration",
|
|
59098
|
+
"mocha.opts": "testing_configuration",
|
|
59099
|
+
"nodemon.json": "development_configuration",
|
|
59100
|
+
"nodemon.js": "development_configuration",
|
|
59101
|
+
"next.config.ts": "framework_configuration",
|
|
59102
|
+
"next.config.js": "framework_configuration",
|
|
59103
|
+
"nuxt.config.js": "framework_configuration",
|
|
59104
|
+
"nuxt.config.ts": "framework_configuration",
|
|
59105
|
+
"postcss.config.mjs": "css_processing_configuration",
|
|
59106
|
+
"postcss.config.js": "css_processing_configuration",
|
|
59107
|
+
"tailwind.config.js": "css_framework_configuration",
|
|
59108
|
+
"tailwind.config.ts": "css_framework_configuration",
|
|
59109
|
+
"supabase/config.toml": "database_service_configuration",
|
|
59110
|
+
"pnpm-workspace.yaml": "package_manager_configuration",
|
|
59111
|
+
"yarn.lock": "dependency_lockfile",
|
|
59112
|
+
"package-lock.json": "dependency_lockfile",
|
|
59113
|
+
"tsconfig.base.json": "compiler_base_configuration",
|
|
59114
|
+
"tsconfig.node.json": "compiler_node_configuration",
|
|
59115
|
+
"tsconfig.app.json": "compiler_app_configuration",
|
|
59116
|
+
"turbo.json": "build_system_configuration",
|
|
59117
|
+
"biome.json": "formatter_linter_configuration",
|
|
59118
|
+
"biome.jsonc": "formatter_linter_configuration",
|
|
59119
|
+
"angular.json": "framework_configuration",
|
|
59120
|
+
"nest-cli.json": "framework_configuration",
|
|
59121
|
+
"remix.config.js": "framework_configuration",
|
|
59122
|
+
"remix.config.ts": "framework_configuration"
|
|
59123
|
+
};
|
|
59124
|
+
return roles[fileName] || "general_configuration";
|
|
59125
|
+
}
|
|
59126
|
+
function getRoleForDocFile(fileName) {
|
|
59127
|
+
const roles = {
|
|
59128
|
+
"README.md": "system_overview",
|
|
59129
|
+
"README.txt": "system_overview",
|
|
59130
|
+
"readme.md": "system_overview",
|
|
59131
|
+
"Readme.md": "system_overview",
|
|
59132
|
+
"CHANGELOG.md": "change_history",
|
|
59133
|
+
"CHANGELOG.txt": "change_history",
|
|
59134
|
+
"LICENSE": "license_terms",
|
|
59135
|
+
"LICENSE.md": "license_terms",
|
|
59136
|
+
"CONTRIBUTING.md": "contribution_guidelines",
|
|
59137
|
+
"NOTICE": "legal_notice",
|
|
59138
|
+
"NOTICE.md": "legal_notice",
|
|
59139
|
+
"SECURITY.md": "security_policy",
|
|
59140
|
+
"CODE_OF_CONDUCT.md": "code_of_conduct",
|
|
59141
|
+
"PULL_REQUEST_TEMPLATE.md": "pull_request_guidelines",
|
|
59142
|
+
"ISSUE_TEMPLATE.md": "issue_reporting_guidelines",
|
|
59143
|
+
"HISTORY.md": "project_history",
|
|
59144
|
+
"AUTHORS": "authorship_information",
|
|
59145
|
+
"THANKS": "acknowledgements",
|
|
59146
|
+
"CITATION.cff": "citation_information",
|
|
59147
|
+
"CITATION.bib": "citation_information"
|
|
59148
|
+
};
|
|
59149
|
+
return roles[fileName] || "documentation";
|
|
59150
|
+
}
|
|
59151
|
+
function getRoleForBuildToolFile(fileName) {
|
|
59152
|
+
const roles = {
|
|
59153
|
+
"typedoc.config.cjs": "documentation_generator",
|
|
59154
|
+
"typedoc.json": "documentation_generator",
|
|
59155
|
+
"typedoc.config.js": "documentation_generator",
|
|
59156
|
+
"typedoc.config.ts": "documentation_generator",
|
|
59157
|
+
"documentation.config.js": "documentation_generator",
|
|
59158
|
+
"docs.config.js": "documentation_generator",
|
|
59159
|
+
"api-extractor.json": "api_documentation_generator",
|
|
59160
|
+
"api-documenter.json": "api_documentation_generator",
|
|
59161
|
+
"jsdoc.json": "documentation_generator",
|
|
59162
|
+
"jsdoc.config.json": "documentation_generator",
|
|
59163
|
+
"compodoc.json": "angular_documentation_generator",
|
|
59164
|
+
"documentation.yml": "documentation_generator"
|
|
59165
|
+
};
|
|
59166
|
+
return roles[fileName] || "build_tool_configuration";
|
|
59167
|
+
}
|
|
59168
|
+
function generateAssumptions() {
|
|
59169
|
+
return [
|
|
59170
|
+
"Dynamic imports resolved statically where possible",
|
|
59171
|
+
"Runtime reflection not fully captured",
|
|
59172
|
+
"Only code reachable from entry points analyzed",
|
|
59173
|
+
"Third-party dependencies treated as black boxes",
|
|
59174
|
+
"Build-time code generation not reflected in static analysis",
|
|
59175
|
+
"ArcVision prioritizes execution-relevant structure over exhaustive file indexing. Non-runtime files are represented as envelope metadata unless they directly affect execution."
|
|
59176
|
+
];
|
|
59177
|
+
}
|
|
59178
|
+
module2.exports = { buildContext, getGitInfo, calculateIntegrityHash, generateAssumptions, generateStructuralLayers, generateProjectEnvelope, generateAdaptiveStructuralLayers };
|
|
58639
59179
|
}
|
|
58640
59180
|
});
|
|
58641
59181
|
|
|
@@ -65222,7 +65762,9 @@ var require_scanner = __commonJS({
|
|
|
65222
65762
|
const contextOptions = {
|
|
65223
65763
|
directory,
|
|
65224
65764
|
projectName: path2.basename(directory),
|
|
65225
|
-
contextSurface
|
|
65765
|
+
contextSurface,
|
|
65766
|
+
arcvisionVersion: process.env.npm_package_version || "0.1.0"
|
|
65767
|
+
// Pass version from package.json
|
|
65226
65768
|
};
|
|
65227
65769
|
let context = buildContext(nodes, edges, symbols, contextOptions);
|
|
65228
65770
|
console.log(" Validating structural context...");
|
|
@@ -65244,6 +65786,199 @@ var require_scanner = __commonJS({
|
|
|
65244
65786
|
}
|
|
65245
65787
|
});
|
|
65246
65788
|
|
|
65789
|
+
// src/core/diff-analyzer.js
|
|
65790
|
+
var require_diff_analyzer = __commonJS({
|
|
65791
|
+
"src/core/diff-analyzer.js"(exports2, module2) {
|
|
65792
|
+
function generateDiffSummary2(oldContext, newContext) {
|
|
65793
|
+
const diffSummary = {
|
|
65794
|
+
nodes_added: 0,
|
|
65795
|
+
nodes_removed: 0,
|
|
65796
|
+
edges_added: 0,
|
|
65797
|
+
edges_removed: 0,
|
|
65798
|
+
roles_changed: 0,
|
|
65799
|
+
blast_radius_changes: 0
|
|
65800
|
+
};
|
|
65801
|
+
const oldNodeMap = new Map(oldContext.nodes.map((node) => [node.path, node]));
|
|
65802
|
+
const newNodeMap = new Map(newContext.nodes.map((node) => [node.path, node]));
|
|
65803
|
+
for (const [path2, node] of newNodeMap) {
|
|
65804
|
+
if (!oldNodeMap.has(path2)) {
|
|
65805
|
+
diffSummary.nodes_added++;
|
|
65806
|
+
}
|
|
65807
|
+
}
|
|
65808
|
+
for (const [path2, node] of oldNodeMap) {
|
|
65809
|
+
if (!newNodeMap.has(path2)) {
|
|
65810
|
+
diffSummary.nodes_removed++;
|
|
65811
|
+
}
|
|
65812
|
+
}
|
|
65813
|
+
const oldEdgeMap = new Map(
|
|
65814
|
+
oldContext.edges.map((edge) => [`${edge.from}::${edge.to}::${edge.relation}`, edge])
|
|
65815
|
+
);
|
|
65816
|
+
const newEdgeMap = new Map(
|
|
65817
|
+
newContext.edges.map((edge) => [`${edge.from}::${edge.to}::${edge.relation}`, edge])
|
|
65818
|
+
);
|
|
65819
|
+
for (const [key, edge] of newEdgeMap) {
|
|
65820
|
+
if (!oldEdgeMap.has(key)) {
|
|
65821
|
+
diffSummary.edges_added++;
|
|
65822
|
+
}
|
|
65823
|
+
}
|
|
65824
|
+
for (const [key, edge] of oldEdgeMap) {
|
|
65825
|
+
if (!newEdgeMap.has(key)) {
|
|
65826
|
+
diffSummary.edges_removed++;
|
|
65827
|
+
}
|
|
65828
|
+
}
|
|
65829
|
+
for (const newNode of newContext.nodes) {
|
|
65830
|
+
const oldNode = oldNodeMap.get(newNode.path);
|
|
65831
|
+
if (oldNode && oldNode.role !== newNode.role) {
|
|
65832
|
+
diffSummary.roles_changed++;
|
|
65833
|
+
}
|
|
65834
|
+
}
|
|
65835
|
+
for (const newNode of newContext.nodes) {
|
|
65836
|
+
const oldNode = oldNodeMap.get(newNode.path);
|
|
65837
|
+
if (oldNode && oldNode.blast_radius !== newNode.blast_radius) {
|
|
65838
|
+
diffSummary.blast_radius_changes++;
|
|
65839
|
+
}
|
|
65840
|
+
}
|
|
65841
|
+
return {
|
|
65842
|
+
diff_summary: diffSummary
|
|
65843
|
+
};
|
|
65844
|
+
}
|
|
65845
|
+
module2.exports = { generateDiffSummary: generateDiffSummary2 };
|
|
65846
|
+
}
|
|
65847
|
+
});
|
|
65848
|
+
|
|
65849
|
+
// src/core/readme-generator.js
|
|
65850
|
+
var require_readme_generator = __commonJS({
|
|
65851
|
+
"src/core/readme-generator.js"(exports2, module2) {
|
|
65852
|
+
var fs2 = require("fs");
|
|
65853
|
+
var path2 = require("path");
|
|
65854
|
+
var { spawnSync } = require("child_process");
|
|
65855
|
+
function getCommitHash() {
|
|
65856
|
+
try {
|
|
65857
|
+
const result = spawnSync("git", ["rev-parse", "HEAD"], {
|
|
65858
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
65859
|
+
});
|
|
65860
|
+
if (result.status === 0) {
|
|
65861
|
+
return result.stdout.toString().trim();
|
|
65862
|
+
}
|
|
65863
|
+
return "unknown";
|
|
65864
|
+
} catch (error) {
|
|
65865
|
+
return "unknown";
|
|
65866
|
+
}
|
|
65867
|
+
}
|
|
65868
|
+
function generateReadmeContent(commitHash, timestamp, toolVersion, blastRadiusData = null) {
|
|
65869
|
+
let content = `# ArcVision System Context Artifact
|
|
65870
|
+
|
|
65871
|
+
|
|
65872
|
+
## What This Is [arcvision.context.json](./arcvision.context.json)
|
|
65873
|
+
|
|
65874
|
+
This file is the **canonical structural context** of this codebase.
|
|
65875
|
+
It represents how the system actually works \u2014 not how it is described.
|
|
65876
|
+
|
|
65877
|
+
It is generated directly from source code by ArcVision.
|
|
65878
|
+
|
|
65879
|
+
## What This Replaces
|
|
65880
|
+
|
|
65881
|
+
This artifact replaces:
|
|
65882
|
+
- Manual repository scanning
|
|
65883
|
+
- Tribal knowledge held by senior engineers
|
|
65884
|
+
- Re-explaining the system to new developers
|
|
65885
|
+
- Re-prompting LLMs with partial or incorrect context
|
|
65886
|
+
- Guessing blast radius of changes
|
|
65887
|
+
|
|
65888
|
+
## When You Must Use This
|
|
65889
|
+
|
|
65890
|
+
Use this artifact when:
|
|
65891
|
+
- Onboarding a new developer
|
|
65892
|
+
- Prompting an AI assistant about this codebase
|
|
65893
|
+
- Making architectural changes
|
|
65894
|
+
- Investigating unexpected behavior
|
|
65895
|
+
- Assessing risk before modifying core modules
|
|
65896
|
+
|
|
65897
|
+
## What This Artifact Contains
|
|
65898
|
+
|
|
65899
|
+
- Canonical module and dependency graph
|
|
65900
|
+
- Execution and data flow relationships
|
|
65901
|
+
- Structural roles (service, store, boundary, etc.)
|
|
65902
|
+
- Invariants inferred from the system
|
|
65903
|
+
- Impact metrics (blast radius, coupling)
|
|
65904
|
+
|
|
65905
|
+
## Determinism & Trust
|
|
65906
|
+
|
|
65907
|
+
- Generated from commit: ${commitHash}
|
|
65908
|
+
- Generation timestamp: ${timestamp}
|
|
65909
|
+
- Tool version: ${toolVersion}
|
|
65910
|
+
- Deterministic: same input \u2192 same output
|
|
65911
|
+
- Explicit assumptions listed inside the artifact
|
|
65912
|
+
|
|
65913
|
+
If this artifact conflicts with human memory, **trust the artifact**.`;
|
|
65914
|
+
if (blastRadiusData && blastRadiusData.topFiles && blastRadiusData.topFiles.length > 0) {
|
|
65915
|
+
content += `
|
|
65916
|
+
|
|
65917
|
+
## Structural Context Hubs
|
|
65918
|
+
|
|
65919
|
+
The following files have the highest blast radius and represent critical structural hubs in the system:
|
|
65920
|
+
|
|
65921
|
+
`;
|
|
65922
|
+
blastRadiusData.topFiles.forEach((item, index) => {
|
|
65923
|
+
let warningMessage = "";
|
|
65924
|
+
if (index === 0) {
|
|
65925
|
+
warningMessage = "Changes here may silently propagate across the system.";
|
|
65926
|
+
} else if (index === 1) {
|
|
65927
|
+
warningMessage = "Acts as a coordination layer between components.";
|
|
65928
|
+
} else {
|
|
65929
|
+
warningMessage = "Modifications can cause widespread inconsistencies.";
|
|
65930
|
+
}
|
|
65931
|
+
content += `- **${item.file}**
|
|
65932
|
+
- Blast Radius: ${item.blastRadius} files (${item.percentOfGraph}% of codebase)
|
|
65933
|
+
- Risk: ${warningMessage}
|
|
65934
|
+
|
|
65935
|
+
`;
|
|
65936
|
+
});
|
|
65937
|
+
} else {
|
|
65938
|
+
content += `
|
|
65939
|
+
|
|
65940
|
+
## Structural Context Hubs
|
|
65941
|
+
|
|
65942
|
+
No high-structure files detected based on import dependencies.`;
|
|
65943
|
+
}
|
|
65944
|
+
content += `
|
|
65945
|
+
|
|
65946
|
+
## How to Use With AI
|
|
65947
|
+
|
|
65948
|
+
When prompting AI tools, include this file as system context.
|
|
65949
|
+
Do not ask the AI to infer architecture without it.
|
|
65950
|
+
|
|
65951
|
+
## When to Regenerate
|
|
65952
|
+
|
|
65953
|
+
Regenerate this artifact when:
|
|
65954
|
+
- Core modules change
|
|
65955
|
+
- New services are added
|
|
65956
|
+
- Dependency structure shifts
|
|
65957
|
+
|
|
65958
|
+
Run:
|
|
65959
|
+
|
|
65960
|
+
\`\`\`
|
|
65961
|
+
arcvision scan --upload
|
|
65962
|
+
\`\`\`
|
|
65963
|
+
|
|
65964
|
+
## Source of Truth
|
|
65965
|
+
|
|
65966
|
+
This artifact is the **source of truth** for system structure.
|
|
65967
|
+
All explanations, decisions, and AI reasoning should reference it.`;
|
|
65968
|
+
return content;
|
|
65969
|
+
}
|
|
65970
|
+
function generateReadme(outputDir, toolVersion, blastRadiusData = null) {
|
|
65971
|
+
const commitHash = getCommitHash();
|
|
65972
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
65973
|
+
const readmeContent = generateReadmeContent(commitHash, timestamp, toolVersion, blastRadiusData);
|
|
65974
|
+
const readmePath = path2.join(outputDir, "README.md");
|
|
65975
|
+
fs2.writeFileSync(readmePath, readmeContent);
|
|
65976
|
+
console.log(`\u2705 System context README generated at ${readmePath}`);
|
|
65977
|
+
}
|
|
65978
|
+
module2.exports = { generateReadme, generateReadmeContent, getCommitHash };
|
|
65979
|
+
}
|
|
65980
|
+
});
|
|
65981
|
+
|
|
65247
65982
|
// src/index.js
|
|
65248
65983
|
var { Command } = require_commander();
|
|
65249
65984
|
var chalk = require_source();
|
|
@@ -65251,6 +65986,7 @@ var path = require("path");
|
|
|
65251
65986
|
var fs = require("fs");
|
|
65252
65987
|
var os = require("os");
|
|
65253
65988
|
var scanner = require_scanner();
|
|
65989
|
+
var { generateDiffSummary } = require_diff_analyzer();
|
|
65254
65990
|
var version = "1.0.0";
|
|
65255
65991
|
try {
|
|
65256
65992
|
const packageJsonPath = path.join(__dirname, "../package.json");
|
|
@@ -65267,7 +66003,9 @@ function analyzeBlastRadius(architectureMap) {
|
|
|
65267
66003
|
if (architectureMap.nodes && architectureMap.nodes.length > 0) {
|
|
65268
66004
|
architectureMap.nodes.forEach((node) => {
|
|
65269
66005
|
let blastRadius = 0;
|
|
65270
|
-
if (node.
|
|
66006
|
+
if (node.blast_radius !== void 0) {
|
|
66007
|
+
blastRadius = node.blast_radius;
|
|
66008
|
+
} else if (node.metadata && node.metadata.blast_radius !== void 0) {
|
|
65271
66009
|
blastRadius = node.metadata.blast_radius;
|
|
65272
66010
|
} else if (node.signals && node.signals.blast_radius !== void 0) {
|
|
65273
66011
|
blastRadius = node.signals.blast_radius;
|
|
@@ -65463,11 +66201,15 @@ program.command("scan").description("Scan the current directory and generate arc
|
|
|
65463
66201
|
}
|
|
65464
66202
|
if (options.upload) {
|
|
65465
66203
|
await uploadToDatabase(map);
|
|
66204
|
+
const { generateReadme } = require_readme_generator();
|
|
66205
|
+
generateReadme(".", version, blastRadiusAnalysis);
|
|
65466
66206
|
} else {
|
|
65467
66207
|
const fs2 = require("fs");
|
|
65468
66208
|
const outputFileName = "arcvision.context.json";
|
|
65469
66209
|
fs2.writeFileSync(outputFileName, JSON.stringify(map, null, 2));
|
|
65470
66210
|
console.log(chalk.green(`\u2705 Structural context saved to ${outputFileName}`));
|
|
66211
|
+
const { generateReadme } = require_readme_generator();
|
|
66212
|
+
generateReadme(".", version, blastRadiusAnalysis);
|
|
65471
66213
|
console.log(chalk.dim("\nUse --upload to send to dashboard."));
|
|
65472
66214
|
}
|
|
65473
66215
|
} catch (error) {
|
|
@@ -65492,4 +66234,29 @@ program.command("scan").description("Scan the current directory and generate arc
|
|
|
65492
66234
|
}
|
|
65493
66235
|
}
|
|
65494
66236
|
});
|
|
66237
|
+
program.command("diff").description("Compare two context artifacts and generate diff summary").argument("<old-file>", "Path to the old context artifact").argument("<new-file>", "Path to the new context artifact").action(async (oldFile, newFile) => {
|
|
66238
|
+
try {
|
|
66239
|
+
console.log(chalk.blue(`Comparing context artifacts:`));
|
|
66240
|
+
console.log(chalk.blue(` Old: ${oldFile}`));
|
|
66241
|
+
console.log(chalk.blue(` New: ${newFile}`));
|
|
66242
|
+
const oldContext = JSON.parse(fs.readFileSync(oldFile, "utf8"));
|
|
66243
|
+
const newContext = JSON.parse(fs.readFileSync(newFile, "utf8"));
|
|
66244
|
+
const diffResult = generateDiffSummary(oldContext, newContext);
|
|
66245
|
+
newContext.diff_summary = diffResult.diff_summary;
|
|
66246
|
+
const outputFileName = "arcvision.context.diff.json";
|
|
66247
|
+
fs.writeFileSync(outputFileName, JSON.stringify(newContext, null, 2));
|
|
66248
|
+
console.log(chalk.green("\u2705 Structural diff completed!"));
|
|
66249
|
+
console.log(chalk.green(`\u2705 Diff summary saved to ${outputFileName}`));
|
|
66250
|
+
console.log(chalk.yellow("\nDiff Summary:"));
|
|
66251
|
+
console.log(chalk.yellow(` Nodes Added: ${diffResult.diff_summary.nodes_added}`));
|
|
66252
|
+
console.log(chalk.yellow(` Nodes Removed: ${diffResult.diff_summary.nodes_removed}`));
|
|
66253
|
+
console.log(chalk.yellow(` Edges Added: ${diffResult.diff_summary.edges_added}`));
|
|
66254
|
+
console.log(chalk.yellow(` Edges Removed: ${diffResult.diff_summary.edges_removed}`));
|
|
66255
|
+
console.log(chalk.yellow(` Roles Changed: ${diffResult.diff_summary.roles_changed}`));
|
|
66256
|
+
console.log(chalk.yellow(` Blast Radius Changes: ${diffResult.diff_summary.blast_radius_changes}`));
|
|
66257
|
+
} catch (error) {
|
|
66258
|
+
console.error(chalk.red("\u274C Diff failed:"), error.message);
|
|
66259
|
+
process.exit(1);
|
|
66260
|
+
}
|
|
66261
|
+
});
|
|
65495
66262
|
program.parse();
|
package/package.json
CHANGED
|
@@ -8,7 +8,12 @@
|
|
|
8
8
|
"system",
|
|
9
9
|
"nodes",
|
|
10
10
|
"edges",
|
|
11
|
-
"metrics"
|
|
11
|
+
"metrics",
|
|
12
|
+
"assumptions",
|
|
13
|
+
"source",
|
|
14
|
+
"integrity",
|
|
15
|
+
"structural_layers",
|
|
16
|
+
"project_envelope"
|
|
12
17
|
],
|
|
13
18
|
"properties": {
|
|
14
19
|
"schema_version": {
|
|
@@ -79,6 +84,138 @@
|
|
|
79
84
|
"additionalProperties": {
|
|
80
85
|
"type": ["number", "string"]
|
|
81
86
|
}
|
|
87
|
+
},
|
|
88
|
+
"assumptions": {
|
|
89
|
+
"type": "array",
|
|
90
|
+
"description": "Explicit assumptions about analysis limitations",
|
|
91
|
+
"items": {
|
|
92
|
+
"type": "string"
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
"source": {
|
|
96
|
+
"type": "object",
|
|
97
|
+
"description": "Source repository and commit information",
|
|
98
|
+
"required": ["repo", "commit", "generated_at", "arcvision_version"],
|
|
99
|
+
"properties": {
|
|
100
|
+
"repo": { "type": "string" },
|
|
101
|
+
"commit": { "type": "string" },
|
|
102
|
+
"generated_at": { "type": "string" },
|
|
103
|
+
"arcvision_version": { "type": "string" }
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"integrity": {
|
|
107
|
+
"type": "object",
|
|
108
|
+
"description": "Integrity hash of the artifact",
|
|
109
|
+
"required": ["sha256"],
|
|
110
|
+
"properties": {
|
|
111
|
+
"sha256": { "type": "string" }
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
"structural_layers": {
|
|
115
|
+
"type": "object",
|
|
116
|
+
"description": "Defines which structural layers are included in the analysis",
|
|
117
|
+
"required": ["runtime_code", "execution_scripts", "infrastructure_scripts", "configuration", "documentation", "assets"],
|
|
118
|
+
"properties": {
|
|
119
|
+
"runtime_code": {
|
|
120
|
+
"type": "object",
|
|
121
|
+
"required": ["status", "description"],
|
|
122
|
+
"properties": {
|
|
123
|
+
"status": { "type": "string", "enum": ["included", "excluded"] },
|
|
124
|
+
"description": { "type": "string" }
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"execution_scripts": {
|
|
128
|
+
"type": "object",
|
|
129
|
+
"required": ["status", "description"],
|
|
130
|
+
"properties": {
|
|
131
|
+
"status": { "type": "string", "enum": ["included", "excluded"] },
|
|
132
|
+
"description": { "type": "string" }
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
"infrastructure_scripts": {
|
|
136
|
+
"type": "object",
|
|
137
|
+
"required": ["status", "description"],
|
|
138
|
+
"properties": {
|
|
139
|
+
"status": { "type": "string", "enum": ["included", "excluded"] },
|
|
140
|
+
"description": { "type": "string" }
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
"configuration": {
|
|
144
|
+
"type": "object",
|
|
145
|
+
"required": ["status", "description"],
|
|
146
|
+
"properties": {
|
|
147
|
+
"status": { "type": "string", "enum": ["included", "excluded", "optional"] },
|
|
148
|
+
"description": { "type": "string" }
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
"documentation": {
|
|
152
|
+
"type": "object",
|
|
153
|
+
"required": ["status", "description"],
|
|
154
|
+
"properties": {
|
|
155
|
+
"status": { "type": "string", "enum": ["included", "excluded", "optional"] },
|
|
156
|
+
"description": { "type": "string" }
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
"assets": {
|
|
160
|
+
"type": "object",
|
|
161
|
+
"required": ["status", "description"],
|
|
162
|
+
"properties": {
|
|
163
|
+
"status": { "type": "string", "enum": ["included", "excluded"] },
|
|
164
|
+
"description": { "type": "string" }
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
"project_envelope": {
|
|
170
|
+
"type": "object",
|
|
171
|
+
"description": "Project-level files that provide context but are not execution graph nodes",
|
|
172
|
+
"properties": {
|
|
173
|
+
"configuration_files": {
|
|
174
|
+
"type": "array",
|
|
175
|
+
"items": {
|
|
176
|
+
"type": "object",
|
|
177
|
+
"properties": {
|
|
178
|
+
"path": { "type": "string" },
|
|
179
|
+
"role": { "type": "string" }
|
|
180
|
+
},
|
|
181
|
+
"required": ["path", "role"]
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
"documentation": {
|
|
185
|
+
"type": "array",
|
|
186
|
+
"items": {
|
|
187
|
+
"type": "object",
|
|
188
|
+
"properties": {
|
|
189
|
+
"path": { "type": "string" },
|
|
190
|
+
"role": { "type": "string" }
|
|
191
|
+
},
|
|
192
|
+
"required": ["path", "role"]
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
"build_tools": {
|
|
196
|
+
"type": "array",
|
|
197
|
+
"items": {
|
|
198
|
+
"type": "object",
|
|
199
|
+
"properties": {
|
|
200
|
+
"path": { "type": "string" },
|
|
201
|
+
"role": { "type": "string" }
|
|
202
|
+
},
|
|
203
|
+
"required": ["path", "role"]
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
"diff_summary": {
|
|
209
|
+
"type": "object",
|
|
210
|
+
"description": "Structural diff summary between commits",
|
|
211
|
+
"properties": {
|
|
212
|
+
"nodes_added": { "type": "number" },
|
|
213
|
+
"nodes_removed": { "type": "number" },
|
|
214
|
+
"edges_added": { "type": "number" },
|
|
215
|
+
"edges_removed": { "type": "number" },
|
|
216
|
+
"roles_changed": { "type": "number" },
|
|
217
|
+
"blast_radius_changes": { "type": "number" }
|
|
218
|
+
}
|
|
82
219
|
}
|
|
83
220
|
}
|
|
84
221
|
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
-
"title": "Arcvision System-Level Structural Context",
|
|
4
|
-
"type": "object",
|
|
5
|
-
"required": [
|
|
6
|
-
"schema_version",
|
|
7
|
-
"generated_at",
|
|
8
|
-
"system",
|
|
9
|
-
"nodes",
|
|
10
|
-
"edges",
|
|
11
|
-
"metrics"
|
|
12
|
-
],
|
|
13
|
-
"properties": {
|
|
14
|
-
"schema_version": {
|
|
15
|
-
"type": "string",
|
|
16
|
-
"description": "Semantic version of the Arcvision context schema (e.g. 1.0.0)"
|
|
17
|
-
},
|
|
18
|
-
"generated_at": {
|
|
19
|
-
"type": "string",
|
|
20
|
-
"format": "date-time",
|
|
21
|
-
"description": "ISO-8601 timestamp when context was generated"
|
|
22
|
-
},
|
|
23
|
-
"system": {
|
|
24
|
-
"type": "object",
|
|
25
|
-
"required": ["name", "root_path", "language"],
|
|
26
|
-
"properties": {
|
|
27
|
-
"name": { "type": "string" },
|
|
28
|
-
"root_path": { "type": "string" },
|
|
29
|
-
"language": { "type": "string" }
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
"nodes": {
|
|
33
|
-
"type": "array",
|
|
34
|
-
"items": {
|
|
35
|
-
"type": "object",
|
|
36
|
-
"required": ["id", "type", "path", "role"],
|
|
37
|
-
"properties": {
|
|
38
|
-
"id": {
|
|
39
|
-
"type": "string",
|
|
40
|
-
"description": "Deterministic, stable ID (never random)"
|
|
41
|
-
},
|
|
42
|
-
"type": {
|
|
43
|
-
"type": "string",
|
|
44
|
-
"enum": ["file", "module", "class", "function", "service"]
|
|
45
|
-
},
|
|
46
|
-
"path": {
|
|
47
|
-
"type": "string",
|
|
48
|
-
"description": "Normalized relative path"
|
|
49
|
-
},
|
|
50
|
-
"role": {
|
|
51
|
-
"type": "string",
|
|
52
|
-
"description": "Why this node exists in the system"
|
|
53
|
-
},
|
|
54
|
-
"dependencies": {
|
|
55
|
-
"type": "array",
|
|
56
|
-
"items": { "type": "string" }
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
"edges": {
|
|
62
|
-
"type": "array",
|
|
63
|
-
"items": {
|
|
64
|
-
"type": "object",
|
|
65
|
-
"required": ["from", "to", "relation"],
|
|
66
|
-
"properties": {
|
|
67
|
-
"from": { "type": "string" },
|
|
68
|
-
"to": { "type": "string" },
|
|
69
|
-
"relation": {
|
|
70
|
-
"type": "string",
|
|
71
|
-
"enum": ["imports", "calls", "owns", "depends_on"]
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
"metrics": {
|
|
77
|
-
"type": "object",
|
|
78
|
-
"description": "System-wide aggregate metrics",
|
|
79
|
-
"additionalProperties": {
|
|
80
|
-
"type": ["number", "string"]
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|