@veewo/gitnexus 1.5.0-rc.2 → 1.5.0-rc.4

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.
@@ -51,10 +51,23 @@ export function applyUnityRuntimeBindingRules(graph, rules, _config) {
51
51
  else if (rel.type === 'UNITY_COMPONENT_INSTANCE')
52
52
  componentInstances.push(rel);
53
53
  }
54
+ // Pre-build scene file index: lowercase scene name → fileId[]
55
+ const sceneFilesByName = new Map();
56
+ for (const node of graph.iterNodes()) {
57
+ if (node.label !== 'File')
58
+ continue;
59
+ const filePath = String(node.properties.filePath ?? '');
60
+ if (!filePath.endsWith('.unity'))
61
+ continue;
62
+ const fileName = (filePath.split('/').pop() ?? '').replace(/\.unity$/, '').toLowerCase();
63
+ const list = sceneFilesByName.get(fileName) ?? [];
64
+ list.push(node.id);
65
+ sceneFilesByName.set(fileName, list);
66
+ }
54
67
  for (const rule of rules) {
55
68
  let ruleEdges = 0;
56
69
  for (const binding of rule.resource_bindings ?? []) {
57
- ruleEdges += processBinding(binding, rule.id, assetGuidRefs, componentInstances, methodsByClassId, classNodes, addSyntheticEdge);
70
+ ruleEdges += processBinding(binding, rule.id, assetGuidRefs, componentInstances, methodsByClassId, classNodes, sceneFilesByName, addSyntheticEdge);
58
71
  }
59
72
  if (rule.lifecycle_overrides?.additional_entry_points?.length) {
60
73
  ruleEdges += processLifecycleOverrides(rule, methodsByClassId, classNodes, addSyntheticEdge);
@@ -78,13 +91,19 @@ function findMethodsOnResource(resourceFileId, componentInstances, methodsByClas
78
91
  }
79
92
  return results;
80
93
  }
81
- function processBinding(binding, ruleId, assetGuidRefs, componentInstances, methodsByClassId, classNodes, addEdge) {
94
+ function processBinding(binding, ruleId, assetGuidRefs, componentInstances, methodsByClassId, classNodes, sceneFilesByName, addEdge) {
82
95
  if (binding.kind === 'asset_ref_loads_components') {
83
96
  return processAssetRefLoadsComponents(binding, ruleId, assetGuidRefs, componentInstances, methodsByClassId, addEdge);
84
97
  }
85
98
  if (binding.kind === 'method_triggers_field_load') {
86
99
  return processMethodTriggersFieldLoad(binding, ruleId, assetGuidRefs, componentInstances, methodsByClassId, classNodes, addEdge);
87
100
  }
101
+ if (binding.kind === 'method_triggers_scene_load') {
102
+ return processMethodTriggersSceneLoad(binding, ruleId, componentInstances, methodsByClassId, classNodes, sceneFilesByName, addEdge);
103
+ }
104
+ if (binding.kind === 'method_triggers_method') {
105
+ return processMethodTriggersMethod(binding, ruleId, methodsByClassId, classNodes, addEdge);
106
+ }
88
107
  return 0;
89
108
  }
90
109
  function processAssetRefLoadsComponents(binding, ruleId, assetGuidRefs, componentInstances, methodsByClassId, addEdge) {
@@ -157,6 +176,65 @@ function processMethodTriggersFieldLoad(binding, ruleId, assetGuidRefs, componen
157
176
  }
158
177
  return count;
159
178
  }
179
+ function processMethodTriggersSceneLoad(binding, ruleId, componentInstances, methodsByClassId, classNodes, sceneFilesByName, addEdge) {
180
+ const classPattern = binding.host_class_pattern ? new RegExp(binding.host_class_pattern) : null;
181
+ const loaderMethodNames = new Set(binding.loader_methods ?? []);
182
+ const sceneName = binding.scene_name;
183
+ const defaultEntryPoints = ['OnEnable', 'Awake', 'Start'];
184
+ const entryPoints = (binding.target_entry_points ?? []).length > 0
185
+ ? binding.target_entry_points
186
+ : defaultEntryPoints;
187
+ if (!classPattern || loaderMethodNames.size === 0 || !sceneName)
188
+ return 0;
189
+ const sceneFileIds = sceneFilesByName.get(sceneName.toLowerCase()) ?? [];
190
+ if (sceneFileIds.length === 0)
191
+ return 0;
192
+ let count = 0;
193
+ for (const cls of classNodes) {
194
+ if (!classPattern.test(cls.properties.name))
195
+ continue;
196
+ const methods = methodsByClassId.get(cls.id) ?? [];
197
+ const loaders = methods.filter(m => loaderMethodNames.has(m.properties.name));
198
+ if (loaders.length === 0)
199
+ continue;
200
+ for (const sceneFileId of sceneFileIds) {
201
+ const targetMethods = findMethodsOnResource(sceneFileId, componentInstances, methodsByClassId, entryPoints);
202
+ for (const loader of loaders) {
203
+ for (const target of targetMethods) {
204
+ if (addEdge(loader.id, target.id, `unity-rule-scene-load:${ruleId}`))
205
+ count++;
206
+ }
207
+ }
208
+ }
209
+ }
210
+ return count;
211
+ }
212
+ function processMethodTriggersMethod(binding, ruleId, methodsByClassId, classNodes, addEdge) {
213
+ const { source_class_pattern, source_method, target_class_pattern, target_method } = binding;
214
+ if (!source_class_pattern || !source_method || !target_class_pattern || !target_method)
215
+ return 0;
216
+ const srcPattern = new RegExp(source_class_pattern);
217
+ const tgtPattern = new RegExp(target_class_pattern);
218
+ let sourceMethodId;
219
+ let targetMethodId;
220
+ for (const cls of classNodes) {
221
+ if (!sourceMethodId && srcPattern.test(cls.properties.name)) {
222
+ const match = (methodsByClassId.get(cls.id) ?? []).find(m => m.properties.name === source_method);
223
+ if (match)
224
+ sourceMethodId = match.id;
225
+ }
226
+ if (!targetMethodId && tgtPattern.test(cls.properties.name)) {
227
+ const match = (methodsByClassId.get(cls.id) ?? []).find(m => m.properties.name === target_method);
228
+ if (match)
229
+ targetMethodId = match.id;
230
+ }
231
+ if (sourceMethodId && targetMethodId)
232
+ break;
233
+ }
234
+ if (!sourceMethodId || !targetMethodId)
235
+ return 0;
236
+ return addEdge(sourceMethodId, targetMethodId, `unity-rule-method-bridge:${ruleId}`) ? 1 : 0;
237
+ }
160
238
  function processLifecycleOverrides(rule, methodsByClassId, classNodes, addEdge) {
161
239
  const overrides = rule.lifecycle_overrides;
162
240
  if (!overrides?.additional_entry_points?.length)
@@ -41,7 +41,7 @@ export declare const ANNOTATION_SCHEMA: string;
41
41
  export declare const CONSTRUCTOR_SCHEMA: string;
42
42
  export declare const TEMPLATE_SCHEMA: string;
43
43
  export declare const MODULE_SCHEMA: string;
44
- export declare const RELATION_SCHEMA = "\nCREATE REL TABLE CodeRelation (\n FROM File TO File,\n FROM File TO Folder,\n FROM File TO Function,\n FROM File TO Class,\n FROM File TO Interface,\n FROM File TO Method,\n FROM File TO CodeElement,\n FROM File TO `Struct`,\n FROM File TO `Enum`,\n FROM File TO `Macro`,\n FROM File TO `Typedef`,\n FROM File TO `Union`,\n FROM File TO `Namespace`,\n FROM File TO `Trait`,\n FROM File TO `Impl`,\n FROM File TO `TypeAlias`,\n FROM File TO `Const`,\n FROM File TO `Static`,\n FROM File TO `Property`,\n FROM File TO `Record`,\n FROM File TO `Delegate`,\n FROM File TO `Annotation`,\n FROM File TO `Constructor`,\n FROM File TO `Template`,\n FROM File TO `Module`,\n FROM Folder TO Folder,\n FROM Folder TO File,\n FROM Function TO Function,\n FROM Function TO Method,\n FROM Function TO Class,\n FROM Function TO Community,\n FROM Function TO `Macro`,\n FROM Function TO `Struct`,\n FROM Function TO `Template`,\n FROM Function TO `Enum`,\n FROM Function TO `Namespace`,\n FROM Function TO `TypeAlias`,\n FROM Function TO `Module`,\n FROM Function TO `Impl`,\n FROM Function TO Interface,\n FROM Function TO `Constructor`,\n FROM Function TO `Const`,\n FROM Function TO `Typedef`,\n FROM Function TO `Union`,\n FROM Function TO `Property`,\n FROM Class TO Method,\n FROM Class TO Function,\n FROM Class TO File,\n FROM Class TO Class,\n FROM Class TO Interface,\n FROM Class TO Community,\n FROM Class TO `Template`,\n FROM Class TO `TypeAlias`,\n FROM Class TO `Struct`,\n FROM Class TO `Enum`,\n FROM Class TO `Annotation`,\n FROM Class TO `Constructor`,\n FROM Class TO `Trait`,\n FROM Class TO `Macro`,\n FROM Class TO `Impl`,\n FROM Class TO `Union`,\n FROM Class TO `Namespace`,\n FROM Class TO `Typedef`,\n FROM Class TO `Property`,\n FROM Class TO `Delegate`,\n FROM Method TO Function,\n FROM Method TO Method,\n FROM Method TO Class,\n FROM Method TO Community,\n FROM Method TO `Template`,\n FROM Method TO `Struct`,\n FROM Method TO `TypeAlias`,\n FROM Method TO `Enum`,\n FROM Method TO `Macro`,\n FROM Method TO `Namespace`,\n FROM Method TO `Module`,\n FROM Method TO `Impl`,\n FROM Method TO Interface,\n FROM Method TO `Constructor`,\n FROM Method TO `Property`,\n FROM Method TO `Delegate`,\n FROM `Template` TO `Template`,\n FROM `Template` TO Function,\n FROM `Template` TO Method,\n FROM `Template` TO Class,\n FROM `Template` TO `Struct`,\n FROM `Template` TO `TypeAlias`,\n FROM `Template` TO `Enum`,\n FROM `Template` TO `Macro`,\n FROM `Template` TO Interface,\n FROM `Template` TO `Constructor`,\n FROM `Module` TO `Module`,\n FROM CodeElement TO Community,\n FROM Interface TO Community,\n FROM Interface TO Function,\n FROM Interface TO Method,\n FROM Interface TO Class,\n FROM Interface TO Interface,\n FROM Interface TO `TypeAlias`,\n FROM Interface TO `Struct`,\n FROM Interface TO `Constructor`,\n FROM Interface TO `Property`,\n FROM `Struct` TO Community,\n FROM `Struct` TO `Trait`,\n FROM `Struct` TO `Struct`,\n FROM `Struct` TO Class,\n FROM `Struct` TO `Enum`,\n FROM `Struct` TO Function,\n FROM `Struct` TO Method,\n FROM `Struct` TO Interface,\n FROM `Struct` TO `Constructor`,\n FROM `Struct` TO `Property`,\n FROM `Enum` TO `Enum`,\n FROM `Enum` TO Community,\n FROM `Enum` TO Class,\n FROM `Enum` TO Interface,\n FROM `Macro` TO Community,\n FROM `Macro` TO Function,\n FROM `Macro` TO Method,\n FROM `Module` TO Function,\n FROM `Module` TO Method,\n FROM `Typedef` TO Community,\n FROM `Union` TO Community,\n FROM `Namespace` TO Community,\n FROM `Namespace` TO `Struct`,\n FROM `Trait` TO Method,\n FROM `Trait` TO `Constructor`,\n FROM `Trait` TO `Property`,\n FROM `Trait` TO Community,\n FROM `Impl` TO Method,\n FROM `Impl` TO `Constructor`,\n FROM `Impl` TO `Property`,\n FROM `Impl` TO Community,\n FROM `Impl` TO `Trait`,\n FROM `Impl` TO `Struct`,\n FROM `Impl` TO `Impl`,\n FROM `TypeAlias` TO Community,\n FROM `TypeAlias` TO `Trait`,\n FROM `TypeAlias` TO Class,\n FROM `Const` TO Community,\n FROM `Static` TO Community,\n FROM `Property` TO Community,\n FROM `Property` TO Class,\n FROM `Property` TO Interface,\n FROM `Record` TO Method,\n FROM `Record` TO `Constructor`,\n FROM `Record` TO `Property`,\n FROM `Record` TO Community,\n FROM `Delegate` TO Community,\n FROM `Annotation` TO Community,\n FROM `Constructor` TO Community,\n FROM `Constructor` TO Interface,\n FROM `Constructor` TO Class,\n FROM `Constructor` TO Method,\n FROM `Constructor` TO Function,\n FROM `Constructor` TO `Constructor`,\n FROM `Constructor` TO `Struct`,\n FROM `Constructor` TO `Macro`,\n FROM `Constructor` TO `Template`,\n FROM `Constructor` TO `TypeAlias`,\n FROM `Constructor` TO `Enum`,\n FROM `Constructor` TO `Annotation`,\n FROM `Constructor` TO `Impl`,\n FROM `Constructor` TO `Namespace`,\n FROM `Constructor` TO `Module`,\n FROM `Constructor` TO `Property`,\n FROM `Constructor` TO `Typedef`,\n FROM `Template` TO Community,\n FROM `Module` TO Community,\n FROM Function TO Process,\n FROM Method TO Process,\n FROM Class TO Process,\n FROM Interface TO Process,\n FROM `Struct` TO Process,\n FROM `Constructor` TO Process,\n FROM `Module` TO Process,\n FROM `Macro` TO Process,\n FROM `Impl` TO Process,\n FROM `Typedef` TO Process,\n FROM `TypeAlias` TO Process,\n FROM `Enum` TO Process,\n FROM `Union` TO Process,\n FROM `Namespace` TO Process,\n FROM `Trait` TO Process,\n FROM `Const` TO Process,\n FROM `Static` TO Process,\n FROM `Property` TO Process,\n FROM `Record` TO Process,\n FROM `Delegate` TO Process,\n FROM `Annotation` TO Process,\n FROM `Template` TO Process,\n FROM CodeElement TO Process,\n type STRING,\n confidence DOUBLE,\n reason STRING,\n step INT32\n)";
44
+ export declare const RELATION_SCHEMA = "\nCREATE REL TABLE CodeRelation (\n FROM File TO File,\n FROM File TO Folder,\n FROM File TO Function,\n FROM File TO Class,\n FROM File TO Interface,\n FROM File TO Method,\n FROM File TO CodeElement,\n FROM File TO `Struct`,\n FROM File TO `Enum`,\n FROM File TO `Macro`,\n FROM File TO `Typedef`,\n FROM File TO `Union`,\n FROM File TO `Namespace`,\n FROM File TO `Trait`,\n FROM File TO `Impl`,\n FROM File TO `TypeAlias`,\n FROM File TO `Const`,\n FROM File TO `Static`,\n FROM File TO `Property`,\n FROM File TO `Record`,\n FROM File TO `Delegate`,\n FROM File TO `Annotation`,\n FROM File TO `Constructor`,\n FROM File TO `Template`,\n FROM File TO `Module`,\n FROM Folder TO Folder,\n FROM Folder TO File,\n FROM Function TO Function,\n FROM Function TO Method,\n FROM Function TO Class,\n FROM Function TO Community,\n FROM Function TO `Macro`,\n FROM Function TO `Struct`,\n FROM Function TO `Template`,\n FROM Function TO `Enum`,\n FROM Function TO `Namespace`,\n FROM Function TO `TypeAlias`,\n FROM Function TO `Module`,\n FROM Function TO `Impl`,\n FROM Function TO Interface,\n FROM Function TO `Constructor`,\n FROM Function TO `Const`,\n FROM Function TO `Typedef`,\n FROM Function TO `Union`,\n FROM Function TO `Property`,\n FROM Class TO Method,\n FROM Class TO Function,\n FROM Class TO File,\n FROM Class TO Class,\n FROM Class TO Interface,\n FROM Class TO Community,\n FROM Class TO `Template`,\n FROM Class TO `TypeAlias`,\n FROM Class TO `Struct`,\n FROM Class TO `Enum`,\n FROM Class TO `Annotation`,\n FROM Class TO `Constructor`,\n FROM Class TO `Trait`,\n FROM Class TO `Macro`,\n FROM Class TO `Impl`,\n FROM Class TO `Union`,\n FROM Class TO `Namespace`,\n FROM Class TO `Typedef`,\n FROM Class TO `Property`,\n FROM Class TO `Delegate`,\n FROM Method TO Function,\n FROM Method TO Method,\n FROM Method TO Class,\n FROM Method TO Community,\n FROM Method TO `Template`,\n FROM Method TO `Struct`,\n FROM Method TO `TypeAlias`,\n FROM Method TO `Enum`,\n FROM Method TO `Macro`,\n FROM Method TO `Namespace`,\n FROM Method TO `Module`,\n FROM Method TO `Impl`,\n FROM Method TO Interface,\n FROM Method TO `Constructor`,\n FROM Method TO `Property`,\n FROM Method TO `Delegate`,\n FROM Method TO `Record`,\n FROM `Template` TO `Template`,\n FROM `Template` TO Function,\n FROM `Template` TO Method,\n FROM `Template` TO Class,\n FROM `Template` TO `Struct`,\n FROM `Template` TO `TypeAlias`,\n FROM `Template` TO `Enum`,\n FROM `Template` TO `Macro`,\n FROM `Template` TO Interface,\n FROM `Template` TO `Constructor`,\n FROM `Module` TO `Module`,\n FROM CodeElement TO Community,\n FROM Interface TO Community,\n FROM Interface TO Function,\n FROM Interface TO Method,\n FROM Interface TO Class,\n FROM Interface TO Interface,\n FROM Interface TO `TypeAlias`,\n FROM Interface TO `Struct`,\n FROM Interface TO `Constructor`,\n FROM Interface TO `Property`,\n FROM `Struct` TO Community,\n FROM `Struct` TO `Trait`,\n FROM `Struct` TO `Struct`,\n FROM `Struct` TO Class,\n FROM `Struct` TO `Enum`,\n FROM `Struct` TO Function,\n FROM `Struct` TO Method,\n FROM `Struct` TO Interface,\n FROM `Struct` TO `Constructor`,\n FROM `Struct` TO `Property`,\n FROM `Enum` TO `Enum`,\n FROM `Enum` TO Community,\n FROM `Enum` TO Class,\n FROM `Enum` TO Interface,\n FROM `Macro` TO Community,\n FROM `Macro` TO Function,\n FROM `Macro` TO Method,\n FROM `Module` TO Function,\n FROM `Module` TO Method,\n FROM `Typedef` TO Community,\n FROM `Union` TO Community,\n FROM `Namespace` TO Community,\n FROM `Namespace` TO `Struct`,\n FROM `Trait` TO Method,\n FROM `Trait` TO `Constructor`,\n FROM `Trait` TO `Property`,\n FROM `Trait` TO Community,\n FROM `Impl` TO Method,\n FROM `Impl` TO `Constructor`,\n FROM `Impl` TO `Property`,\n FROM `Impl` TO Community,\n FROM `Impl` TO `Trait`,\n FROM `Impl` TO `Struct`,\n FROM `Impl` TO `Impl`,\n FROM `TypeAlias` TO Community,\n FROM `TypeAlias` TO `Trait`,\n FROM `TypeAlias` TO Class,\n FROM `Const` TO Community,\n FROM `Static` TO Community,\n FROM `Property` TO Community,\n FROM `Property` TO Class,\n FROM `Property` TO Interface,\n FROM `Record` TO Method,\n FROM `Record` TO `Constructor`,\n FROM `Record` TO `Property`,\n FROM `Record` TO Community,\n FROM `Delegate` TO Community,\n FROM `Annotation` TO Community,\n FROM `Constructor` TO Community,\n FROM `Constructor` TO Interface,\n FROM `Constructor` TO Class,\n FROM `Constructor` TO Method,\n FROM `Constructor` TO Function,\n FROM `Constructor` TO `Constructor`,\n FROM `Constructor` TO `Struct`,\n FROM `Constructor` TO `Macro`,\n FROM `Constructor` TO `Template`,\n FROM `Constructor` TO `TypeAlias`,\n FROM `Constructor` TO `Enum`,\n FROM `Constructor` TO `Annotation`,\n FROM `Constructor` TO `Impl`,\n FROM `Constructor` TO `Namespace`,\n FROM `Constructor` TO `Module`,\n FROM `Constructor` TO `Property`,\n FROM `Constructor` TO `Typedef`,\n FROM `Template` TO Community,\n FROM `Module` TO Community,\n FROM Function TO Process,\n FROM Method TO Process,\n FROM Class TO Process,\n FROM Interface TO Process,\n FROM `Struct` TO Process,\n FROM `Constructor` TO Process,\n FROM `Module` TO Process,\n FROM `Macro` TO Process,\n FROM `Impl` TO Process,\n FROM `Typedef` TO Process,\n FROM `TypeAlias` TO Process,\n FROM `Enum` TO Process,\n FROM `Union` TO Process,\n FROM `Namespace` TO Process,\n FROM `Trait` TO Process,\n FROM `Const` TO Process,\n FROM `Static` TO Process,\n FROM `Property` TO Process,\n FROM `Record` TO Process,\n FROM `Delegate` TO Process,\n FROM `Annotation` TO Process,\n FROM `Template` TO Process,\n FROM CodeElement TO Process,\n type STRING,\n confidence DOUBLE,\n reason STRING,\n step INT32\n)";
45
45
  export declare const EMBEDDING_SCHEMA = "\nCREATE NODE TABLE CodeEmbedding (\n nodeId STRING,\n embedding FLOAT[384],\n PRIMARY KEY (nodeId)\n)";
46
46
  /**
47
47
  * Create vector index for semantic search
@@ -262,6 +262,7 @@ CREATE REL TABLE ${REL_TABLE_NAME} (
262
262
  FROM Method TO \`Constructor\`,
263
263
  FROM Method TO \`Property\`,
264
264
  FROM Method TO \`Delegate\`,
265
+ FROM Method TO \`Record\`,
265
266
  FROM \`Template\` TO \`Template\`,
266
267
  FROM \`Template\` TO Function,
267
268
  FROM \`Template\` TO Method,
@@ -9,6 +9,7 @@ export interface RuntimeClaimRuleCatalogEntry {
9
9
  export interface RuntimeClaimRule {
10
10
  id: string;
11
11
  version: string;
12
+ description?: string;
12
13
  trigger_family: string;
13
14
  resource_types: string[];
14
15
  host_base_type: string[];
@@ -173,6 +173,11 @@ export function parseRuleYaml(raw, filePath) {
173
173
  binding.host_class_pattern = scalar('host_class_pattern');
174
174
  binding.field_name = scalar('field_name');
175
175
  binding.loader_methods = list('loader_methods');
176
+ binding.scene_name = scalar('scene_name');
177
+ binding.source_class_pattern = scalar('source_class_pattern');
178
+ binding.source_method = scalar('source_method');
179
+ binding.target_class_pattern = scalar('target_class_pattern');
180
+ binding.target_method = scalar('target_method');
176
181
  resource_bindings.push(binding);
177
182
  }
178
183
  if (resource_bindings.length === 0)
@@ -76,12 +76,18 @@ export interface RuleDslClaims {
76
76
  next_action: string;
77
77
  }
78
78
  export interface UnityResourceBinding {
79
- kind: 'asset_ref_loads_components' | 'method_triggers_field_load';
79
+ kind: 'asset_ref_loads_components' | 'method_triggers_field_load' | 'method_triggers_scene_load' | 'method_triggers_method';
80
+ description?: string;
80
81
  ref_field_pattern?: string;
81
82
  target_entry_points?: string[];
82
83
  host_class_pattern?: string;
83
84
  field_name?: string;
84
85
  loader_methods?: string[];
86
+ scene_name?: string;
87
+ source_class_pattern?: string;
88
+ source_method?: string;
89
+ target_class_pattern?: string;
90
+ target_method?: string;
85
91
  }
86
92
  export interface LifecycleOverrides {
87
93
  additional_entry_points?: string[];
@@ -90,6 +96,7 @@ export interface LifecycleOverrides {
90
96
  export interface RuleDslDraft {
91
97
  id: string;
92
98
  version: string;
99
+ description?: string;
93
100
  match: RuleDslMatch;
94
101
  topology: RuleDslTopologyHop[];
95
102
  closure: RuleDslClosure;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veewo/gitnexus",
3
- "version": "1.5.0-rc.2",
3
+ "version": "1.5.0-rc.4",
4
4
  "description": "Graph-powered code intelligence for AI agents. Index any codebase, query via MCP or CLI.",
5
5
  "author": "Abhigyan Patwari",
6
6
  "license": "PolyForm-Noncommercial-1.0.0",
@@ -59,6 +59,7 @@ loop:
59
59
  | 目标入口方法 | 加载的资源上哪些方法会被触发? | OnEnable, Awake |
60
60
  | 持有字段的类 | 哪些类持有触发加载的字段? | WeaponPowerUp |
61
61
  | 加载方法 | 哪些方法触发资源加载? | Equip |
62
+ | 动态跳转 | 链路中是否有事件派发或回调(C# Action/SyncList/delegate)? | `NetEventHub.OnPickUpItem → OnClientPickItUp` |
62
63
  | 额外 lifecycle | 项目有自定义入口方法吗? | Init |
63
64
  | lifecycle 范围 | 自定义入口方法的作用范围? | Assets/Code/Graph |
64
65
 
@@ -111,6 +112,8 @@ Grep: pattern="void Init\b|void Setup\b" path=<Assets目录>
111
112
  |---------|-------------|------|
112
113
  | asset GUID 引用 → 目标资源组件激活 | `asset_ref_loads_components` | 序列化字段引用 asset,加载时触发组件 lifecycle |
113
114
  | 方法调用 → 字段引用的资源加载 | `method_triggers_field_load` | 特定方法触发序列化字段引用的资源加载 |
115
+ | 方法调用 → SceneManager.LoadScene → 场景组件激活 | `method_triggers_scene_load` | 特定方法触发场景加载,场景中组件 lifecycle 被触发 |
116
+ | 动态跳转(事件派发/回调/delegate,静态分析不可见) | `method_triggers_method` | 声明"方法 A 动态触发方法 B",注入合成 CALLS 边桥接 gap |
114
117
  | 项目自定义入口方法 | `lifecycle_overrides` | 非标准 Unity lifecycle 的自定义入口 |
115
118
 
116
119
  ### 1.5 生成规则 YAML
@@ -121,6 +124,9 @@ Grep: pattern="void Init\b|void Setup\b" path=<Assets目录>
121
124
  id: unity.<scenario-name>.v2
122
125
  version: 2.0.0
123
126
  family: analyze_rules
127
+ description: >-
128
+ (可选)描述该规则覆盖的业务场景和调用链背景,
129
+ 包括动态跳转的机制说明(事件派发/回调绑定等)。
124
130
  trigger_family: <scenario-name>
125
131
  resource_types:
126
132
  - asset
@@ -153,6 +159,30 @@ resource_bindings:
153
159
  loader_methods:
154
160
  - <method_name>
155
161
 
162
+ # 类型 C(可选):方法触发场景加载,场景中组件 lifecycle 被触发
163
+ - kind: method_triggers_scene_load
164
+ host_class_pattern: "<class_pattern>"
165
+ loader_methods:
166
+ - <method_name>
167
+ scene_name: "<scene_name>" # 匹配 .unity 文件名(不含扩展名)
168
+ target_entry_points:
169
+ - Awake
170
+ - Start
171
+ - OnEnable
172
+
173
+ # 类型 D(可选):声明静态分析无法捕获的动态跳转(事件派发/回调/delegate)
174
+ # 适用场景:C# Action/UnityEvent 事件派发、Mirror SyncList 回调、delegate 绑定等
175
+ # 注入一条 source_method → target_method 的合成 CALLS 边(精确匹配,一条边)
176
+ - kind: method_triggers_method
177
+ description: >-
178
+ 说明动态跳转的机制:例如"A 通过 EventHub.OnXxx?.Invoke() 触发,
179
+ B 在初始化时订阅该事件",或"A 调用 SyncList.Add(),
180
+ 触发 SyncList.Callback 回调到 B"
181
+ source_class_pattern: "<source_class_regex>" # 例如 "^PlayerActor$"
182
+ source_method: "<source_method_name>" # 例如 "ProcessInteractables"
183
+ target_class_pattern: "<target_class_regex>" # 例如 "^NetPlayer$"
184
+ target_method: "<target_method_name>" # 例如 "OnClientPickItUp"
185
+
156
186
  lifecycle_overrides:
157
187
  additional_entry_points:
158
188
  - <custom_entry>
@@ -286,13 +316,15 @@ mcp__gitnexus__cypher:
286
316
  WHEN r.reason CONTAINS 'resource-load' THEN 'resource-load'
287
317
  WHEN r.reason CONTAINS 'lifecycle-override' THEN 'lifecycle-override'
288
318
  WHEN r.reason CONTAINS 'loader-bridge' THEN 'loader-bridge'
319
+ WHEN r.reason CONTAINS 'scene-load' THEN 'scene-load'
320
+ WHEN r.reason CONTAINS 'method-bridge' THEN 'method-bridge'
289
321
  ELSE 'other'
290
322
  END AS edgeKind,
291
323
  count(*) AS cnt
292
324
  repo: <repo-name>
293
325
  ```
294
326
 
295
- **PASS**: 三种边类型(resource-load, lifecycle-override, loader-bridge)均有产出。
327
+ **PASS**: 规则涉及的边类型均有产出(`method_triggers_method` 对应 `method-bridge`)。
296
328
 
297
329
  ---
298
330
 
@@ -302,9 +334,12 @@ mcp__gitnexus__cypher:
302
334
  |------|---------|---------|
303
335
  | 验证 1 失败(0 合成边) | 规则未被 compile 或 family 不对 | 检查 catalog.json + compiled bundle |
304
336
  | 验证 1 部分(只有 resource-load) | method_triggers_field_load 参数错误 | 检查 host_class_pattern / loader_methods |
337
+ | 验证 1 部分(无 scene-load) | method_triggers_scene_load 参数错误 | 检查 scene_name 是否匹配 .unity 文件名 |
338
+ | 验证 1 部分(无 method-bridge) | method_triggers_method 类名/方法名不匹配 | 检查 source/target_class_pattern 和 source/target_method 是否与图谱中节点名一致 |
305
339
  | 验证 2 失败(rule_not_matched) | trigger_tokens 未匹配查询文本 | 调整 match.trigger_tokens |
306
340
  | 验证 2 失败(verification_failed) | 合成边 reason 中的 ruleId 不匹配 | 检查规则 ID 一致性 |
307
341
  | 验证 3 失败(无 Process) | 合成边 confidence 过低 | 检查 RULE_EDGE_CONFIDENCE(应为 0.75) |
342
+ | 验证 4 链路断裂(中间有动态跳转) | 事件派发/回调/delegate 无静态 CALLS 边 | 添加 `method_triggers_method` binding 桥接动态跳转 |
308
343
  | lifecycle_overrides 无效 | scope 值不是文件路径前缀 | scope 应匹配 filePath 而非类名 |
309
344
 
310
345
  ---
@@ -314,5 +349,5 @@ mcp__gitnexus__cypher:
314
349
  - 设计文档:`docs/plans/2026-04-04-unity-rule-gen-skill-design.md`
315
350
  - YAML 格式定义:设计文档 section 3.3
316
351
  - 注入逻辑:`gitnexus/src/core/ingestion/unity-runtime-binding-rules.ts`
317
- - 规则类型定义:`gitnexus/src/rule-lab/types.ts:90-102`
352
+ - 规则类型定义:`gitnexus/src/rule-lab/types.ts:90-114`
318
353
  - 编译命令:`gitnexus rule-lab compile --repo-path <path>`