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

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.
Files changed (139) hide show
  1. package/dist/benchmark/u2-e2e/hydration-policy-repeatability-runner.d.ts +55 -0
  2. package/dist/benchmark/u2-e2e/hydration-policy-repeatability-runner.js +190 -0
  3. package/dist/benchmark/u2-e2e/hydration-policy-repeatability-runner.test.js +13 -0
  4. package/dist/benchmark/u2-e2e/phase1-process-ref-acceptance-runner.d.ts +22 -0
  5. package/dist/benchmark/u2-e2e/phase1-process-ref-acceptance-runner.js +100 -0
  6. package/dist/benchmark/u2-e2e/phase1-process-ref-acceptance-runner.test.d.ts +1 -0
  7. package/dist/benchmark/u2-e2e/phase1-process-ref-acceptance-runner.test.js +13 -0
  8. package/dist/benchmark/u2-e2e/phase2-runtime-claim-acceptance-runner.d.ts +27 -0
  9. package/dist/benchmark/u2-e2e/phase2-runtime-claim-acceptance-runner.js +118 -0
  10. package/dist/benchmark/u2-e2e/phase2-runtime-claim-acceptance-runner.test.d.ts +1 -0
  11. package/dist/benchmark/u2-e2e/phase2-runtime-claim-acceptance-runner.test.js +16 -0
  12. package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.d.ts +60 -0
  13. package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.js +331 -0
  14. package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.test.d.ts +1 -0
  15. package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.test.js +42 -0
  16. package/dist/benchmark/u2-e2e/reload-v1-acceptance-runner.js +4 -4
  17. package/dist/benchmark/unity-lazy-context-sampler.d.ts +6 -0
  18. package/dist/benchmark/unity-lazy-context-sampler.js +49 -13
  19. package/dist/benchmark/unity-lazy-context-sampler.test.js +4 -0
  20. package/dist/cli/ai-context.js +6 -1
  21. package/dist/cli/eval-server.js +0 -3
  22. package/dist/cli/index.js +8 -0
  23. package/dist/cli/mcp.js +0 -3
  24. package/dist/cli/rule-lab.d.ts +42 -0
  25. package/dist/cli/rule-lab.js +157 -0
  26. package/dist/cli/rule-lab.test.d.ts +1 -0
  27. package/dist/cli/rule-lab.test.js +11 -0
  28. package/dist/cli/tool.d.ts +7 -1
  29. package/dist/cli/tool.js +6 -0
  30. package/dist/core/config/unity-config.d.ts +20 -0
  31. package/dist/core/config/unity-config.js +46 -0
  32. package/dist/core/graph/types.d.ts +1 -1
  33. package/dist/core/ingestion/pipeline.js +38 -13
  34. package/dist/core/ingestion/unity-lifecycle-synthetic-calls.d.ts +0 -2
  35. package/dist/core/ingestion/unity-lifecycle-synthetic-calls.js +26 -213
  36. package/dist/core/ingestion/unity-lifecycle-synthetic-calls.test.js +1 -1
  37. package/dist/core/ingestion/unity-resource-processor.js +87 -22
  38. package/dist/core/ingestion/unity-resource-processor.test.js +67 -2
  39. package/dist/core/ingestion/unity-runtime-binding-rules.d.ts +11 -0
  40. package/dist/core/ingestion/unity-runtime-binding-rules.js +179 -0
  41. package/dist/core/unity/options.d.ts +4 -0
  42. package/dist/core/unity/options.js +18 -0
  43. package/dist/core/unity/options.test.js +11 -1
  44. package/dist/core/unity/resolver.js +11 -1
  45. package/dist/core/unity/resolver.test.js +62 -0
  46. package/dist/core/unity/yaml-object-graph.js +1 -1
  47. package/dist/core/unity/yaml-object-graph.test.js +16 -0
  48. package/dist/mcp/local/derived-process-reader.d.ts +2 -0
  49. package/dist/mcp/local/derived-process-reader.js +15 -0
  50. package/dist/mcp/local/local-backend.d.ts +56 -0
  51. package/dist/mcp/local/local-backend.js +1003 -53
  52. package/dist/mcp/local/local-backend.unity-merge.test.js +1 -1
  53. package/dist/mcp/local/process-confidence.js +1 -1
  54. package/dist/mcp/local/process-evidence.d.ts +1 -0
  55. package/dist/mcp/local/process-evidence.js +22 -0
  56. package/dist/mcp/local/process-evidence.test.js +11 -1
  57. package/dist/mcp/local/process-ref.d.ts +24 -0
  58. package/dist/mcp/local/process-ref.js +33 -0
  59. package/dist/mcp/local/process-ref.test.d.ts +1 -0
  60. package/dist/mcp/local/process-ref.test.js +24 -0
  61. package/dist/mcp/local/runtime-chain-verify.d.ts +15 -1
  62. package/dist/mcp/local/runtime-chain-verify.js +191 -187
  63. package/dist/mcp/local/runtime-chain-verify.test.js +546 -19
  64. package/dist/mcp/local/runtime-claim-rule-registry.d.ts +63 -0
  65. package/dist/mcp/local/runtime-claim-rule-registry.js +308 -0
  66. package/dist/mcp/local/runtime-claim-rule-registry.test.d.ts +1 -0
  67. package/dist/mcp/local/runtime-claim-rule-registry.test.js +215 -0
  68. package/dist/mcp/local/runtime-claim.d.ts +38 -0
  69. package/dist/mcp/local/runtime-claim.js +54 -0
  70. package/dist/mcp/local/runtime-claim.test.d.ts +1 -0
  71. package/dist/mcp/local/runtime-claim.test.js +27 -0
  72. package/dist/mcp/local/unity-enrichment.d.ts +1 -0
  73. package/dist/mcp/local/unity-enrichment.js +1 -1
  74. package/dist/mcp/local/unity-evidence-view.d.ts +26 -0
  75. package/dist/mcp/local/unity-evidence-view.js +96 -0
  76. package/dist/mcp/local/unity-evidence-view.test.d.ts +1 -0
  77. package/dist/mcp/local/unity-evidence-view.test.js +39 -0
  78. package/dist/mcp/local/unity-lazy-hydrator.d.ts +2 -2
  79. package/dist/mcp/local/unity-lazy-hydrator.js +3 -3
  80. package/dist/mcp/local/unity-lazy-hydrator.test.js +4 -4
  81. package/dist/mcp/local/unity-parity-cache.js +2 -6
  82. package/dist/mcp/local/unity-parity-seed-loader.d.ts +1 -0
  83. package/dist/mcp/local/unity-parity-seed-loader.js +10 -16
  84. package/dist/mcp/local/unity-parity-seed-loader.test.js +3 -12
  85. package/dist/mcp/local/unity-runtime-hydration.d.ts +3 -2
  86. package/dist/mcp/local/unity-runtime-hydration.js +13 -16
  87. package/dist/mcp/local/unity-runtime-hydration.test.js +15 -1
  88. package/dist/mcp/resources.js +13 -0
  89. package/dist/mcp/tools.js +166 -13
  90. package/dist/rule-lab/analyze.d.ts +12 -0
  91. package/dist/rule-lab/analyze.js +90 -0
  92. package/dist/rule-lab/analyze.test.d.ts +1 -0
  93. package/dist/rule-lab/analyze.test.js +28 -0
  94. package/dist/rule-lab/compile.d.ts +5 -0
  95. package/dist/rule-lab/compile.js +51 -0
  96. package/dist/rule-lab/compiled-bundles.d.ts +30 -0
  97. package/dist/rule-lab/compiled-bundles.js +36 -0
  98. package/dist/rule-lab/curate.d.ts +32 -0
  99. package/dist/rule-lab/curate.js +134 -0
  100. package/dist/rule-lab/curate.test.d.ts +1 -0
  101. package/dist/rule-lab/curate.test.js +72 -0
  102. package/dist/rule-lab/discover.d.ts +13 -0
  103. package/dist/rule-lab/discover.js +74 -0
  104. package/dist/rule-lab/discover.test.d.ts +1 -0
  105. package/dist/rule-lab/discover.test.js +42 -0
  106. package/dist/rule-lab/paths.d.ts +21 -0
  107. package/dist/rule-lab/paths.js +37 -0
  108. package/dist/rule-lab/paths.test.d.ts +1 -0
  109. package/dist/rule-lab/paths.test.js +46 -0
  110. package/dist/rule-lab/promote.d.ts +26 -0
  111. package/dist/rule-lab/promote.js +314 -0
  112. package/dist/rule-lab/promote.test.d.ts +1 -0
  113. package/dist/rule-lab/promote.test.js +164 -0
  114. package/dist/rule-lab/regress.d.ts +60 -0
  115. package/dist/rule-lab/regress.js +122 -0
  116. package/dist/rule-lab/regress.test.d.ts +1 -0
  117. package/dist/rule-lab/regress.test.js +68 -0
  118. package/dist/rule-lab/review-pack.d.ts +31 -0
  119. package/dist/rule-lab/review-pack.js +125 -0
  120. package/dist/rule-lab/review-pack.test.d.ts +1 -0
  121. package/dist/rule-lab/review-pack.test.js +49 -0
  122. package/dist/rule-lab/types.d.ts +99 -0
  123. package/dist/rule-lab/types.js +1 -0
  124. package/package.json +1 -1
  125. package/skills/_shared/unity-hydration-contract.md +11 -0
  126. package/skills/_shared/unity-ui-trace-contract.md +33 -0
  127. package/skills/gitnexus-cli.md +11 -25
  128. package/skills/gitnexus-guide.md +2 -0
  129. package/skills/gitnexus-unity-rule-gen.md +318 -0
  130. package/dist/core/ingestion/unity-lifecycle-config.d.ts +0 -5
  131. package/dist/core/ingestion/unity-lifecycle-config.js +0 -25
  132. package/dist/mcp/local/unity-lazy-config.d.ts +0 -6
  133. package/dist/mcp/local/unity-lazy-config.js +0 -7
  134. package/dist/mcp/local/unity-lazy-config.test.js +0 -9
  135. package/dist/mcp/local/unity-process-confidence-config.d.ts +0 -1
  136. package/dist/mcp/local/unity-process-confidence-config.js +0 -4
  137. package/dist/mcp/local/unity-runtime-chain-verify-config.d.ts +0 -1
  138. package/dist/mcp/local/unity-runtime-chain-verify-config.js +0 -10
  139. /package/dist/{mcp/local/unity-lazy-config.test.d.ts → benchmark/u2-e2e/hydration-policy-repeatability-runner.test.d.ts} +0 -0
@@ -0,0 +1,42 @@
1
+ import type { Command } from 'commander';
2
+ declare const RULE_LAB_COMMANDS: readonly ["discover", "analyze", "review-pack", "curate", "promote", "regress"];
3
+ type RuleLabHandlerName = 'ruleLabDiscoverCommand' | 'ruleLabAnalyzeCommand' | 'ruleLabReviewPackCommand' | 'ruleLabCurateCommand' | 'ruleLabPromoteCommand' | 'ruleLabRegressCommand';
4
+ type LazyFactory = (handlerName: RuleLabHandlerName) => (...args: any[]) => void | Promise<void>;
5
+ export declare function getRuleLabCommandNames(program: Command): string[];
6
+ export declare function attachRuleLabCommands(program: Command, lazyFactory?: LazyFactory): void;
7
+ export declare function ruleLabDiscoverCommand(options: {
8
+ repoPath?: string;
9
+ scope?: 'full' | 'diff';
10
+ seed?: string;
11
+ }): Promise<void>;
12
+ export declare function ruleLabAnalyzeCommand(options: {
13
+ repoPath?: string;
14
+ runId: string;
15
+ sliceId: string;
16
+ }): Promise<void>;
17
+ export declare function ruleLabReviewPackCommand(options: {
18
+ repoPath?: string;
19
+ runId: string;
20
+ sliceId: string;
21
+ maxTokens?: string | number;
22
+ }): Promise<void>;
23
+ export declare function ruleLabCurateCommand(options: {
24
+ repoPath?: string;
25
+ runId: string;
26
+ sliceId: string;
27
+ inputPath: string;
28
+ }): Promise<void>;
29
+ export declare function ruleLabPromoteCommand(options: {
30
+ repoPath?: string;
31
+ runId: string;
32
+ sliceId: string;
33
+ version?: string;
34
+ }): Promise<void>;
35
+ export declare function ruleLabRegressCommand(options: {
36
+ precision: string | number;
37
+ coverage: string | number;
38
+ repoPath?: string;
39
+ runId?: string;
40
+ probesPath?: string;
41
+ }): Promise<void>;
42
+ export { RULE_LAB_COMMANDS };
@@ -0,0 +1,157 @@
1
+ import { writeSync } from 'node:fs';
2
+ import fs from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { discoverRuleLabRun } from '../rule-lab/discover.js';
5
+ import { analyzeRuleLabSlice } from '../rule-lab/analyze.js';
6
+ import { buildReviewPack } from '../rule-lab/review-pack.js';
7
+ import { curateRuleLabSlice } from '../rule-lab/curate.js';
8
+ import { promoteCuratedRules } from '../rule-lab/promote.js';
9
+ import { runRuleLabRegress } from '../rule-lab/regress.js';
10
+ import { compileRules } from '../rule-lab/compile.js';
11
+ const RULE_LAB_COMMANDS = ['discover', 'analyze', 'review-pack', 'curate', 'promote', 'regress'];
12
+ function output(data) {
13
+ const text = typeof data === 'string' ? data : JSON.stringify(data, null, 2);
14
+ writeSync(1, `${text}\n`);
15
+ }
16
+ function resolveRepoPath(repoPath) {
17
+ return path.resolve(repoPath || process.cwd());
18
+ }
19
+ export function getRuleLabCommandNames(program) {
20
+ const root = program.commands.find((command) => command.name() === 'rule-lab');
21
+ if (!root)
22
+ return [];
23
+ return root.commands.map((command) => command.name());
24
+ }
25
+ export function attachRuleLabCommands(program, lazyFactory) {
26
+ const action = (handlerName) => {
27
+ if (lazyFactory)
28
+ return lazyFactory(handlerName);
29
+ switch (handlerName) {
30
+ case 'ruleLabDiscoverCommand':
31
+ return (options) => ruleLabDiscoverCommand(options);
32
+ case 'ruleLabAnalyzeCommand':
33
+ return (options) => ruleLabAnalyzeCommand(options);
34
+ case 'ruleLabReviewPackCommand':
35
+ return (options) => ruleLabReviewPackCommand(options);
36
+ case 'ruleLabCurateCommand':
37
+ return (options) => ruleLabCurateCommand(options);
38
+ case 'ruleLabPromoteCommand':
39
+ return (options) => ruleLabPromoteCommand(options);
40
+ case 'ruleLabRegressCommand':
41
+ return (options) => ruleLabRegressCommand(options);
42
+ default:
43
+ return () => {
44
+ throw new Error(`Unknown rule lab handler: ${handlerName}`);
45
+ };
46
+ }
47
+ };
48
+ const root = program
49
+ .command('rule-lab')
50
+ .description('Offline rule-lab workflow for discover/analyze/review-pack/curate/promote/regress');
51
+ root
52
+ .command('discover')
53
+ .option('--repo-path <path>', 'Repository path (default: cwd)')
54
+ .option('--scope <scope>', 'Discovery scope: full|diff', 'full')
55
+ .option('--seed <seed>', 'Optional deterministic seed')
56
+ .action(action('ruleLabDiscoverCommand'));
57
+ root
58
+ .command('analyze')
59
+ .requiredOption('--run-id <id>', 'Rule-lab run id')
60
+ .requiredOption('--slice-id <id>', 'Slice id')
61
+ .option('--repo-path <path>', 'Repository path (default: cwd)')
62
+ .action(action('ruleLabAnalyzeCommand'));
63
+ root
64
+ .command('review-pack')
65
+ .requiredOption('--run-id <id>', 'Rule-lab run id')
66
+ .requiredOption('--slice-id <id>', 'Slice id')
67
+ .option('--repo-path <path>', 'Repository path (default: cwd)')
68
+ .option('--max-tokens <n>', 'Token budget', '6000')
69
+ .action(action('ruleLabReviewPackCommand'));
70
+ root
71
+ .command('curate')
72
+ .requiredOption('--run-id <id>', 'Rule-lab run id')
73
+ .requiredOption('--slice-id <id>', 'Slice id')
74
+ .requiredOption('--input-path <path>', 'Path to curation input JSON')
75
+ .option('--repo-path <path>', 'Repository path (default: cwd)')
76
+ .action(action('ruleLabCurateCommand'));
77
+ root
78
+ .command('promote')
79
+ .requiredOption('--run-id <id>', 'Rule-lab run id')
80
+ .requiredOption('--slice-id <id>', 'Slice id')
81
+ .option('--repo-path <path>', 'Repository path (default: cwd)')
82
+ .option('--version <version>', 'Promoted rule version', '1.0.0')
83
+ .action(action('ruleLabPromoteCommand'));
84
+ root
85
+ .command('regress')
86
+ .requiredOption('--precision <n>', 'Precision metric')
87
+ .requiredOption('--coverage <n>', 'Coverage metric')
88
+ .option('--repo-path <path>', 'Repository path (default: cwd)')
89
+ .option('--run-id <id>', 'Run id (if provided, write report to .gitnexus/rules/reports)')
90
+ .option('--probes-path <path>', 'Optional JSON file containing regress probes')
91
+ .action(action('ruleLabRegressCommand'));
92
+ root
93
+ .command('compile')
94
+ .description('Compile approved YAML rules into a JSON bundle')
95
+ .option('--repo-path <path>', 'Repository path (default: cwd)')
96
+ .option('--family <family>', 'Rule family to compile', 'analyze_rules')
97
+ .action((options) => compileRules({ repoPath: options.repoPath, family: options.family }));
98
+ }
99
+ export async function ruleLabDiscoverCommand(options) {
100
+ const result = await discoverRuleLabRun({
101
+ repoPath: resolveRepoPath(options?.repoPath),
102
+ scope: options?.scope || 'full',
103
+ seed: options?.seed,
104
+ });
105
+ output(result);
106
+ }
107
+ export async function ruleLabAnalyzeCommand(options) {
108
+ const result = await analyzeRuleLabSlice({
109
+ repoPath: resolveRepoPath(options?.repoPath),
110
+ runId: options.runId,
111
+ sliceId: options.sliceId,
112
+ });
113
+ output(result);
114
+ }
115
+ export async function ruleLabReviewPackCommand(options) {
116
+ const result = await buildReviewPack({
117
+ repoPath: resolveRepoPath(options?.repoPath),
118
+ runId: options.runId,
119
+ sliceId: options.sliceId,
120
+ maxTokens: Number(options.maxTokens || 6000),
121
+ });
122
+ output(result);
123
+ }
124
+ export async function ruleLabCurateCommand(options) {
125
+ const result = await curateRuleLabSlice({
126
+ repoPath: resolveRepoPath(options?.repoPath),
127
+ runId: options.runId,
128
+ sliceId: options.sliceId,
129
+ inputPath: path.resolve(options.inputPath),
130
+ });
131
+ output(result);
132
+ }
133
+ export async function ruleLabPromoteCommand(options) {
134
+ const result = await promoteCuratedRules({
135
+ repoPath: resolveRepoPath(options?.repoPath),
136
+ runId: options.runId,
137
+ sliceId: options.sliceId,
138
+ version: options.version,
139
+ });
140
+ output(result);
141
+ }
142
+ export async function ruleLabRegressCommand(options) {
143
+ let probes;
144
+ if (options.probesPath) {
145
+ const raw = await fs.readFile(path.resolve(options.probesPath), 'utf-8');
146
+ probes = JSON.parse(raw);
147
+ }
148
+ const result = await runRuleLabRegress({
149
+ precision: Number(options.precision),
150
+ coverage: Number(options.coverage),
151
+ repoPath: options.repoPath ? resolveRepoPath(options.repoPath) : undefined,
152
+ runId: options.runId,
153
+ probes,
154
+ });
155
+ output(result);
156
+ }
157
+ export { RULE_LAB_COMMANDS };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { Command } from 'commander';
3
+ import { attachRuleLabCommands, getRuleLabCommandNames } from './rule-lab.js';
4
+ describe('rule-lab cli', () => {
5
+ it('registers all six rule-lab subcommands', async () => {
6
+ const program = new Command();
7
+ attachRuleLabCommands(program);
8
+ const cmds = getRuleLabCommandNames(program);
9
+ expect(cmds).toEqual(['discover', 'analyze', 'review-pack', 'curate', 'promote', 'regress']);
10
+ });
11
+ });
@@ -14,7 +14,7 @@
14
14
  * native module which captures the Node.js process.stdout stream during init.
15
15
  * See the output() function for details (#324).
16
16
  */
17
- import type { UnityHydrationMode, UnityResourcesMode } from '../core/unity/options.js';
17
+ import type { UnityEvidenceMode, UnityHydrationMode, UnityResourcesMode } from '../core/unity/options.js';
18
18
  export declare function queryCommand(queryText: string, options?: {
19
19
  repo?: string;
20
20
  context?: string;
@@ -24,6 +24,9 @@ export declare function queryCommand(queryText: string, options?: {
24
24
  scopePreset?: 'unity-gameplay' | 'unity-all';
25
25
  unityResources?: UnityResourcesMode;
26
26
  unityHydration?: UnityHydrationMode;
27
+ unityEvidence?: UnityEvidenceMode;
28
+ resourcePathPrefix?: string;
29
+ resourceSeedMode?: 'strict' | 'balanced';
27
30
  runtimeChainVerify?: 'off' | 'on-demand';
28
31
  }): Promise<void>;
29
32
  export declare function contextCommand(name: string, options?: {
@@ -33,6 +36,9 @@ export declare function contextCommand(name: string, options?: {
33
36
  content?: boolean;
34
37
  unityResources?: UnityResourcesMode;
35
38
  unityHydration?: UnityHydrationMode;
39
+ unityEvidence?: UnityEvidenceMode;
40
+ resourcePathPrefix?: string;
41
+ resourceSeedMode?: 'strict' | 'balanced';
36
42
  runtimeChainVerify?: 'off' | 'on-demand';
37
43
  }): Promise<void>;
38
44
  export declare function impactCommand(target: string, options?: {
package/dist/cli/tool.js CHANGED
@@ -94,6 +94,9 @@ export async function queryCommand(queryText, options) {
94
94
  scope_preset: options?.scopePreset,
95
95
  unity_resources: options?.unityResources,
96
96
  unity_hydration_mode: options?.unityHydration,
97
+ unity_evidence_mode: options?.unityEvidence,
98
+ resource_path_prefix: options?.resourcePathPrefix,
99
+ resource_seed_mode: options?.resourceSeedMode,
97
100
  runtime_chain_verify: options?.runtimeChainVerify,
98
101
  repo,
99
102
  });
@@ -113,6 +116,9 @@ export async function contextCommand(name, options) {
113
116
  include_content: options?.content ?? false,
114
117
  unity_resources: options?.unityResources,
115
118
  unity_hydration_mode: options?.unityHydration,
119
+ unity_evidence_mode: options?.unityEvidence,
120
+ resource_path_prefix: options?.resourcePathPrefix,
121
+ resource_seed_mode: options?.resourceSeedMode,
116
122
  runtime_chain_verify: options?.runtimeChainVerify,
117
123
  repo,
118
124
  });
@@ -0,0 +1,20 @@
1
+ export interface UnityConfig {
2
+ maxSyntheticEdgesPerClass: number;
3
+ maxSyntheticEdgesTotal: number;
4
+ lazyMaxPaths: number;
5
+ lazyBatchSize: number;
6
+ lazyMaxMs: number;
7
+ payloadMode: 'compact' | 'full';
8
+ persistLifecycleProcessMetadata: boolean;
9
+ parityWarmup: boolean;
10
+ parityWarmupMaxParallel: number;
11
+ paritySeedCacheIdleMs: number;
12
+ paritySeedCacheMaxEntries: number;
13
+ parityCacheMaxEntries: number;
14
+ }
15
+ export type ConfigSourceMap = Record<keyof UnityConfig, 'cli' | 'config_file' | 'default'>;
16
+ export interface ResolvedUnityConfig {
17
+ config: UnityConfig;
18
+ configSource: ConfigSourceMap;
19
+ }
20
+ export declare function resolveUnityConfig(cliArgs?: Partial<UnityConfig>, configPath?: string): ResolvedUnityConfig;
@@ -0,0 +1,46 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ const DEFAULTS = {
4
+ maxSyntheticEdgesPerClass: 12,
5
+ maxSyntheticEdgesTotal: 256,
6
+ lazyMaxPaths: 120,
7
+ lazyBatchSize: 30,
8
+ lazyMaxMs: 5000,
9
+ payloadMode: 'compact',
10
+ persistLifecycleProcessMetadata: false,
11
+ parityWarmup: false,
12
+ parityWarmupMaxParallel: 4,
13
+ paritySeedCacheIdleMs: 60000,
14
+ paritySeedCacheMaxEntries: 100,
15
+ parityCacheMaxEntries: 500,
16
+ };
17
+ export function resolveUnityConfig(cliArgs, configPath) {
18
+ let fileValues = {};
19
+ try {
20
+ const path = configPath ?? join(process.cwd(), '.gitnexus', 'config.json');
21
+ const raw = JSON.parse(readFileSync(path, 'utf-8'));
22
+ if (raw?.unity && typeof raw.unity === 'object') {
23
+ fileValues = raw.unity;
24
+ }
25
+ }
26
+ catch {
27
+ // missing or invalid config file — skip
28
+ }
29
+ const config = {};
30
+ const configSource = {};
31
+ for (const key of Object.keys(DEFAULTS)) {
32
+ if (cliArgs?.[key] !== undefined) {
33
+ config[key] = cliArgs[key];
34
+ configSource[key] = 'cli';
35
+ }
36
+ else if (fileValues[key] !== undefined) {
37
+ config[key] = fileValues[key];
38
+ configSource[key] = 'config_file';
39
+ }
40
+ else {
41
+ config[key] = DEFAULTS[key];
42
+ configSource[key] = 'default';
43
+ }
44
+ }
45
+ return { config, configSource };
46
+ }
@@ -25,7 +25,7 @@ export type NodeProperties = {
25
25
  parameterCount?: number;
26
26
  returnType?: string;
27
27
  };
28
- export type RelationshipType = 'CONTAINS' | 'CALLS' | 'INHERITS' | 'OVERRIDES' | 'IMPORTS' | 'USES' | 'DEFINES' | 'DECORATES' | 'IMPLEMENTS' | 'EXTENDS' | 'HAS_METHOD' | 'MEMBER_OF' | 'STEP_IN_PROCESS' | 'UNITY_COMPONENT_IN' | 'UNITY_COMPONENT_INSTANCE' | 'UNITY_RESOURCE_SUMMARY' | 'UNITY_SERIALIZED_TYPE_IN';
28
+ export type RelationshipType = 'CONTAINS' | 'CALLS' | 'INHERITS' | 'OVERRIDES' | 'IMPORTS' | 'USES' | 'DEFINES' | 'DECORATES' | 'IMPLEMENTS' | 'EXTENDS' | 'HAS_METHOD' | 'MEMBER_OF' | 'STEP_IN_PROCESS' | 'UNITY_COMPONENT_IN' | 'UNITY_COMPONENT_INSTANCE' | 'UNITY_RESOURCE_SUMMARY' | 'UNITY_SERIALIZED_TYPE_IN' | 'UNITY_ASSET_GUID_REF' | 'UNITY_GRAPH_NODE_SCRIPT_REF';
29
29
  export interface GraphNode {
30
30
  id: string;
31
31
  label: NodeLabel;
@@ -9,7 +9,9 @@ import { processCommunities } from './community-processor.js';
9
9
  import { processProcesses } from './process-processor.js';
10
10
  import { processUnityResources } from './unity-resource-processor.js';
11
11
  import { applyUnityLifecycleSyntheticCalls } from './unity-lifecycle-synthetic-calls.js';
12
- import { resolveUnityLifecycleConfig } from './unity-lifecycle-config.js';
12
+ import { applyUnityRuntimeBindingRules } from './unity-runtime-binding-rules.js';
13
+ import { resolveUnityConfig } from '../config/unity-config.js';
14
+ import { loadAnalyzeRules } from '../../mcp/local/runtime-claim-rule-registry.js';
13
15
  import { createResolutionContext } from './resolution-context.js';
14
16
  import { createASTCache } from './ast-cache.js';
15
17
  import { walkRepositoryPaths, readFileContents, walkUnityResourcePaths } from './filesystem-walker.js';
@@ -290,6 +292,7 @@ export const runPipelineFromRepo = async (repoPath, onProgress, options) => {
290
292
  importCtx.normalizedFileList = null;
291
293
  let communityResult;
292
294
  let processResult;
295
+ let unityResult;
293
296
  if (!options?.skipGraphPhases) {
294
297
  // ── Phase 4.5: Method Resolution Order ──────────────────────────────
295
298
  onProgress({
@@ -344,14 +347,43 @@ export const runPipelineFromRepo = async (repoPath, onProgress, options) => {
344
347
  reason: 'leiden-algorithm',
345
348
  });
346
349
  });
347
- const unityLifecycleConfig = resolveUnityLifecycleConfig(process.env);
348
- const persistLifecycleProcessMetadata = unityLifecycleConfig.persistLifecycleProcessMetadata;
349
- const unityLifecycleSyntheticResult = applyUnityLifecycleSyntheticCalls(graph, unityLifecycleConfig);
350
+ // ── Phase 5.5: Unity resource bindings (before lifecycle injection)
351
+ onProgress({
352
+ phase: 'enriching',
353
+ percent: 93,
354
+ message: 'Extracting Unity resource bindings...',
355
+ stats: { filesProcessed: totalFiles, totalFiles, nodesCreated: graph.nodeCount },
356
+ });
357
+ unityResult = await processUnityResources(graph, { repoPath, scopedPaths: unityScopedPaths });
358
+ // ── Phase 5.6: Unity lifecycle synthetic calls (auto-detect) ────────
359
+ const isUnityProject = allPaths.some(p => p.startsWith('Assets/') && p.endsWith('.cs'));
360
+ const unityConfig = resolveUnityConfig();
361
+ const persistLifecycleProcessMetadata = unityConfig.config.persistLifecycleProcessMetadata ?? false;
362
+ const unityLifecycleSyntheticResult = isUnityProject
363
+ ? applyUnityLifecycleSyntheticCalls(graph, {
364
+ maxSyntheticEdgesPerClass: unityConfig.config.maxSyntheticEdgesPerClass,
365
+ maxSyntheticEdgesTotal: unityConfig.config.maxSyntheticEdgesTotal,
366
+ })
367
+ : { syntheticEdgeCount: 0, lifecycleEdgeCount: 0, loaderEdgeCount: 0, hostCount: 0, rejectedHostCount: 0 };
350
368
  const syntheticEdgeDetail = unityLifecycleSyntheticResult.syntheticEdgeCount > 0
351
369
  ? ` (Unity synthetic edges: ${unityLifecycleSyntheticResult.syntheticEdgeCount})`
352
370
  : '';
353
- if (isDev && unityLifecycleConfig.enabled) {
354
- console.log(`[UnityLifecycle] enabled=${unityLifecycleConfig.enabled} hosts=${unityLifecycleSyntheticResult.hostCount} syntheticEdges=${unityLifecycleSyntheticResult.syntheticEdgeCount} rejectedHosts=${unityLifecycleSyntheticResult.rejectedHostCount}`);
371
+ if (isDev && isUnityProject) {
372
+ console.log(`[UnityLifecycle] auto-detected hosts=${unityLifecycleSyntheticResult.hostCount} syntheticEdges=${unityLifecycleSyntheticResult.syntheticEdgeCount} rejectedHosts=${unityLifecycleSyntheticResult.rejectedHostCount}`);
373
+ }
374
+ // Phase 5.7: rule-driven binding injection (Phase 3)
375
+ try {
376
+ const analyzeRules = await loadAnalyzeRules(repoPath);
377
+ if (analyzeRules.length > 0) {
378
+ const bindingResult = applyUnityRuntimeBindingRules(graph, analyzeRules, unityConfig.config);
379
+ if (isDev && bindingResult.edgesInjected > 0) {
380
+ console.log(`[UnityRuleBinding] injected ${bindingResult.edgesInjected} edges from ${analyzeRules.length} rule(s)`);
381
+ }
382
+ }
383
+ }
384
+ catch (err) {
385
+ // rule catalog missing or invalid — skip silently
386
+ console.warn(`[UnityRuleBinding] failed to load or apply analyze rules: ${err instanceof Error ? err.message : String(err)}`);
355
387
  }
356
388
  // ── Phase 6: Processes ─────────────────────────────────────────────
357
389
  onProgress({
@@ -414,13 +446,6 @@ export const runPipelineFromRepo = async (repoPath, onProgress, options) => {
414
446
  });
415
447
  });
416
448
  }
417
- onProgress({
418
- phase: 'enriching',
419
- percent: 99,
420
- message: 'Extracting Unity resource bindings...',
421
- stats: { filesProcessed: totalFiles, totalFiles, nodesCreated: graph.nodeCount },
422
- });
423
- const unityResult = await processUnityResources(graph, { repoPath, scopedPaths: unityScopedPaths });
424
449
  onProgress({
425
450
  phase: 'complete',
426
451
  percent: 100,
@@ -4,14 +4,12 @@ export interface UnityLifecycleSyntheticConfig {
4
4
  maxSyntheticEdgesPerClass: number;
5
5
  maxSyntheticEdgesTotal: number;
6
6
  lifecycleEdgeConfidence: number;
7
- loaderEdgeConfidence: number;
8
7
  }
9
8
  export declare const DEFAULT_UNITY_LIFECYCLE_SYNTHETIC_CONFIG: UnityLifecycleSyntheticConfig;
10
9
  export interface UnityLifecycleHost {
11
10
  classNode: GraphNode;
12
11
  baseType: 'MonoBehaviour' | 'ScriptableObject';
13
12
  lifecycleCallbacks: GraphNode[];
14
- loaderAnchors: GraphNode[];
15
13
  methods: GraphNode[];
16
14
  }
17
15
  export interface UnityLifecycleSyntheticResult {