@veewo/gitnexus 1.5.6 → 1.5.8

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 (104) hide show
  1. package/dist/benchmark/analyze-runner.d.ts +0 -2
  2. package/dist/benchmark/analyze-runner.js +0 -6
  3. package/dist/benchmark/analyze-runner.test.js +1 -10
  4. package/dist/benchmark/runner.d.ts +0 -2
  5. package/dist/benchmark/runner.js +0 -2
  6. package/dist/benchmark/u2-e2e/neonspark-full-e2e.js +0 -11
  7. package/dist/benchmark/u2-performance-sampler.js +3 -16
  8. package/dist/cli/ai-context.js +1 -7
  9. package/dist/cli/analyze-options.d.ts +19 -6
  10. package/dist/cli/analyze-options.js +76 -71
  11. package/dist/cli/analyze-options.test.js +78 -73
  12. package/dist/cli/analyze-runtime-summary.js +0 -1
  13. package/dist/cli/analyze-runtime-summary.test.js +0 -2
  14. package/dist/cli/analyze-summary.d.ts +0 -2
  15. package/dist/cli/analyze-summary.js +0 -24
  16. package/dist/cli/analyze-summary.test.js +1 -65
  17. package/dist/cli/analyze.d.ts +2 -4
  18. package/dist/cli/analyze.js +14 -30
  19. package/dist/cli/analyze.test.js +9 -15
  20. package/dist/cli/benchmark-agent-context.d.ts +0 -2
  21. package/dist/cli/benchmark-agent-context.js +0 -2
  22. package/dist/cli/benchmark-agent-safe-query-context.d.ts +0 -2
  23. package/dist/cli/benchmark-agent-safe-query-context.js +0 -2
  24. package/dist/cli/benchmark-unity.d.ts +0 -2
  25. package/dist/cli/benchmark-unity.js +0 -2
  26. package/dist/cli/clean.d.ts +2 -3
  27. package/dist/cli/clean.js +4 -25
  28. package/dist/cli/index.js +1 -12
  29. package/dist/core/ingestion/pipeline.js +1 -44
  30. package/dist/mcp/local/agent-safe-response.js +1 -1
  31. package/dist/mcp/local/local-backend.d.ts +0 -23
  32. package/dist/mcp/local/local-backend.js +69 -248
  33. package/dist/mcp/local/runtime-chain-verify.test.js +0 -49
  34. package/dist/mcp/local/runtime-claim-rule-registry.d.ts +0 -11
  35. package/dist/mcp/local/runtime-claim-rule-registry.js +0 -159
  36. package/dist/mcp/local/runtime-claim-rule-registry.test.js +67 -214
  37. package/dist/mcp/tools.js +0 -70
  38. package/dist/storage/repo-manager.d.ts +1 -0
  39. package/dist/types/pipeline.d.ts +0 -3
  40. package/package.json +1 -1
  41. package/skills/gitnexus-cli.md +62 -38
  42. package/vendor/node_modules/node-addon-api/node_addon_api.Makefile +6 -0
  43. package/vendor/node_modules/node-addon-api/node_addon_api.target.mk +122 -0
  44. package/vendor/node_modules/node-addon-api/node_addon_api_except.target.mk +126 -0
  45. package/vendor/node_modules/node-addon-api/node_addon_api_except_all.target.mk +122 -0
  46. package/vendor/node_modules/node-addon-api/node_addon_api_maybe.target.mk +122 -0
  47. package/vendor/tree-sitter-dart/build/Release/.deps/node_modules/node-addon-api/node_addon_api_except.stamp.d +1 -0
  48. package/vendor/tree-sitter-dart/build/node_modules/node-addon-api/node_addon_api_except.stamp +0 -0
  49. package/vendor/tree-sitter-proto/build/Release/.deps/node_modules/node-addon-api/node_addon_api_except.stamp.d +1 -0
  50. package/vendor/tree-sitter-proto/build/node_modules/node-addon-api/node_addon_api_except.stamp +0 -0
  51. package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.d.ts +0 -60
  52. package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.js +0 -395
  53. package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.test.d.ts +0 -1
  54. package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.test.js +0 -41
  55. package/dist/cli/rule-lab.d.ts +0 -38
  56. package/dist/cli/rule-lab.js +0 -148
  57. package/dist/cli/rule-lab.test.d.ts +0 -1
  58. package/dist/cli/rule-lab.test.js +0 -31
  59. package/dist/cli/scope-manifest-config.d.ts +0 -9
  60. package/dist/cli/scope-manifest-config.js +0 -37
  61. package/dist/cli/sync-manifest.d.ts +0 -27
  62. package/dist/cli/sync-manifest.js +0 -200
  63. package/dist/cli/sync-manifest.test.d.ts +0 -1
  64. package/dist/cli/sync-manifest.test.js +0 -88
  65. package/dist/core/ingestion/unity-runtime-binding-rules.d.ts +0 -26
  66. package/dist/core/ingestion/unity-runtime-binding-rules.js +0 -408
  67. package/dist/rule-lab/analyze.d.ts +0 -13
  68. package/dist/rule-lab/analyze.js +0 -125
  69. package/dist/rule-lab/analyze.test.d.ts +0 -1
  70. package/dist/rule-lab/analyze.test.js +0 -246
  71. package/dist/rule-lab/compile.d.ts +0 -5
  72. package/dist/rule-lab/compile.js +0 -51
  73. package/dist/rule-lab/compiled-bundles.d.ts +0 -30
  74. package/dist/rule-lab/compiled-bundles.js +0 -36
  75. package/dist/rule-lab/curate.d.ts +0 -33
  76. package/dist/rule-lab/curate.js +0 -155
  77. package/dist/rule-lab/curate.test.d.ts +0 -1
  78. package/dist/rule-lab/curate.test.js +0 -137
  79. package/dist/rule-lab/curation-input-builder.d.ts +0 -45
  80. package/dist/rule-lab/curation-input-builder.js +0 -133
  81. package/dist/rule-lab/discover.d.ts +0 -13
  82. package/dist/rule-lab/discover.js +0 -74
  83. package/dist/rule-lab/discover.test.d.ts +0 -1
  84. package/dist/rule-lab/discover.test.js +0 -42
  85. package/dist/rule-lab/paths.d.ts +0 -21
  86. package/dist/rule-lab/paths.js +0 -37
  87. package/dist/rule-lab/paths.test.d.ts +0 -1
  88. package/dist/rule-lab/paths.test.js +0 -46
  89. package/dist/rule-lab/promote.d.ts +0 -26
  90. package/dist/rule-lab/promote.js +0 -387
  91. package/dist/rule-lab/promote.test.d.ts +0 -1
  92. package/dist/rule-lab/promote.test.js +0 -314
  93. package/dist/rule-lab/regress.d.ts +0 -60
  94. package/dist/rule-lab/regress.js +0 -122
  95. package/dist/rule-lab/regress.test.d.ts +0 -1
  96. package/dist/rule-lab/regress.test.js +0 -68
  97. package/dist/rule-lab/review-pack.d.ts +0 -34
  98. package/dist/rule-lab/review-pack.js +0 -165
  99. package/dist/rule-lab/review-pack.test.d.ts +0 -1
  100. package/dist/rule-lab/review-pack.test.js +0 -116
  101. package/dist/rule-lab/types.d.ts +0 -135
  102. package/dist/rule-lab/types.js +0 -1
  103. package/skills/_shared/unity-rule-authoring-contract.md +0 -64
  104. package/skills/gitnexus-unity-rule-gen.md +0 -107
@@ -1,24 +1,14 @@
1
1
  import assert from 'node:assert/strict';
2
- import fs from 'node:fs/promises';
3
- import os from 'node:os';
4
- import path from 'node:path';
5
2
  import { test } from 'vitest';
6
- import { RuleRegistryLoadError, loadRuleRegistry } from './runtime-claim-rule-registry.js';
7
- test('loads active runtime claim rules from project catalog', async () => {
8
- const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'gitnexus-runtime-claim-rules-'));
9
- const repoPath = path.join(tempRoot, 'repo');
10
- const rulesRoot = path.join(repoPath, '.gitnexus', 'rules');
11
- await fs.mkdir(path.join(rulesRoot, 'approved'), { recursive: true });
12
- await fs.writeFile(path.join(rulesRoot, 'catalog.json'), JSON.stringify({
13
- rules: [
14
- {
15
- id: 'demo.reload.rule.v1',
16
- version: '1.2.3',
17
- file: 'approved/demo.reload.rule.v1.yaml',
18
- },
19
- ],
20
- }), 'utf-8');
21
- await fs.writeFile(path.join(rulesRoot, 'approved', 'demo.reload.rule.v1.yaml'), [
3
+ import { RuleRegistryLoadError, parseRuleYaml } from './runtime-claim-rule-registry.js';
4
+ test('RuleRegistryLoadError has code and context', () => {
5
+ const err = new RuleRegistryLoadError('rule_catalog_missing', 'Catalog not found', { repoPath: '/tmp/repo' });
6
+ assert.ok(err instanceof RuleRegistryLoadError);
7
+ assert.equal(err.code, 'rule_catalog_missing');
8
+ assert.match(String(err.message || ''), /Catalog not found/);
9
+ });
10
+ test('parseRuleYaml parses basic fields', () => {
11
+ const yaml = [
22
12
  'id: demo.reload.rule.v1',
23
13
  'version: 1.2.3',
24
14
  'trigger_family: reload',
@@ -33,106 +23,37 @@ test('loads active runtime claim rules from project catalog', async () => {
33
23
  'non_guarantees:',
34
24
  ' - no_runtime_execution',
35
25
  'next_action: gitnexus query "reload"',
36
- ].join('\n'), 'utf-8');
37
- try {
38
- const registry = await loadRuleRegistry(repoPath);
39
- assert.equal(registry.activeRules[0].id, 'demo.reload.rule.v1');
40
- assert.equal(registry.activeRules[0].version, '1.2.3');
41
- }
42
- finally {
43
- await fs.rm(tempRoot, { recursive: true, force: true });
44
- }
45
- });
46
- test('throws rule_catalog_missing when target repo has no catalog (no ancestor fallback)', async () => {
47
- const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'gitnexus-runtime-claim-rules-'));
48
- const workspaceRoot = path.join(tempRoot, 'workspace');
49
- const nestedCwd = path.join(workspaceRoot, 'packages', 'app');
50
- const rulesRoot = path.join(workspaceRoot, '.gitnexus', 'rules');
51
- const catalogPath = path.join(rulesRoot, 'catalog.json');
52
- await fs.mkdir(path.join(rulesRoot, 'approved'), { recursive: true });
53
- await fs.mkdir(nestedCwd, { recursive: true });
54
- await fs.writeFile(catalogPath, JSON.stringify({
55
- rules: [
56
- {
57
- id: 'demo.reload.rule.v1',
58
- version: '1.2.3',
59
- file: 'approved/demo.reload.rule.v1.yaml',
60
- },
61
- ],
62
- }), 'utf-8');
63
- await fs.writeFile(path.join(rulesRoot, 'approved', 'demo.reload.rule.v1.yaml'), ['id: demo.reload.rule.v1', 'version: 1.2.3', 'trigger_family: reload'].join('\n'), 'utf-8');
64
- const originalCwd = process.cwd();
65
- process.chdir(nestedCwd);
66
- try {
67
- await assert.rejects(() => loadRuleRegistry(path.join(tempRoot, 'does-not-exist')), (error) => {
68
- assert.ok(error instanceof RuleRegistryLoadError);
69
- assert.equal(error.code, 'rule_catalog_missing');
70
- assert.match(String(error.message || ''), /catalog not found/i);
71
- return true;
72
- });
73
- }
74
- finally {
75
- process.chdir(originalCwd);
76
- await fs.rm(tempRoot, { recursive: true, force: true });
77
- }
78
- });
79
- test('throws rule_catalog_missing when rulesRoot exists but catalog.json is missing', async () => {
80
- const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'gitnexus-runtime-claim-rules-'));
81
- const repoPath = path.join(tempRoot, 'repo');
82
- const rulesRoot = path.join(repoPath, '.gitnexus', 'rules');
83
- await fs.mkdir(path.join(rulesRoot, 'approved'), { recursive: true });
84
- try {
85
- await assert.rejects(() => loadRuleRegistry(repoPath), (error) => {
86
- assert.ok(error instanceof RuleRegistryLoadError);
87
- assert.equal(error.code, 'rule_catalog_missing');
88
- return true;
89
- });
90
- }
91
- finally {
92
- await fs.rm(tempRoot, { recursive: true, force: true });
93
- }
94
- });
95
- test('throws rule_file_missing when catalog entry points to missing yaml file', async () => {
96
- const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'gitnexus-runtime-claim-rules-'));
97
- const repoPath = path.join(tempRoot, 'repo');
98
- const rulesRoot = path.join(repoPath, '.gitnexus', 'rules');
99
- await fs.mkdir(path.join(rulesRoot, 'approved'), { recursive: true });
100
- await fs.writeFile(path.join(rulesRoot, 'catalog.json'), JSON.stringify({
101
- rules: [
102
- {
103
- id: 'demo.reload.rule.v1',
104
- version: '1.0.0',
105
- file: 'approved/demo.reload.rule.v1.yaml',
106
- },
107
- ],
108
- }), 'utf-8');
109
- try {
110
- await assert.rejects(() => loadRuleRegistry(repoPath), (error) => {
111
- assert.ok(error instanceof RuleRegistryLoadError);
112
- assert.equal(error.code, 'rule_file_missing');
113
- assert.match(String(error.message || ''), /rule file not found/i);
114
- return true;
115
- });
116
- }
117
- finally {
118
- await fs.rm(tempRoot, { recursive: true, force: true });
119
- }
26
+ 'match:',
27
+ ' trigger_tokens:',
28
+ ' - reload',
29
+ 'closure:',
30
+ ' required_hops:',
31
+ ' - resource',
32
+ 'claims:',
33
+ ' guarantees:',
34
+ ' - reload_chain_closed',
35
+ ' non_guarantees:',
36
+ ' - no_runtime_execution',
37
+ ' next_action: gitnexus query "reload"',
38
+ 'topology:',
39
+ ' - hop: resource',
40
+ ' from:',
41
+ ' entity: resource',
42
+ ' to:',
43
+ ' entity: script',
44
+ ' edge:',
45
+ ' kind: binds_script',
46
+ ].join('\n');
47
+ const rule = parseRuleYaml(yaml, 'test.yaml');
48
+ assert.equal(rule.id, 'demo.reload.rule.v1');
49
+ assert.equal(rule.version, '1.2.3');
50
+ assert.equal(rule.trigger_family, 'reload');
51
+ assert.deepEqual(rule.resource_types, ['asset']);
52
+ assert.deepEqual(rule.host_base_type, ['ReloadBase']);
53
+ assert.equal(rule.file_path, 'test.yaml');
120
54
  });
121
- test('parses scalar/list values with spaces, quotes, and escapes without truncation', async () => {
122
- const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'gitnexus-runtime-claim-rules-'));
123
- const repoPath = path.join(tempRoot, 'repo');
124
- const rulesRoot = path.join(repoPath, '.gitnexus', 'rules');
125
- await fs.mkdir(path.join(rulesRoot, 'approved'), { recursive: true });
126
- await fs.writeFile(path.join(rulesRoot, 'catalog.json'), JSON.stringify({
127
- rules: [
128
- {
129
- id: 'demo.scalar-parser.v1',
130
- version: '1.0.0',
131
- file: 'approved/demo.scalar-parser.v1.yaml',
132
- },
133
- ],
134
- }), 'utf-8');
135
- await fs.writeFile(path.join(rulesRoot, 'approved', 'demo.scalar-parser.v1.yaml'), [
55
+ test('parseRuleYaml parses scalar/list values with spaces, quotes, and escapes', () => {
56
+ const yaml = [
136
57
  'id: demo.scalar-parser.v1',
137
58
  'version: 1.0.0',
138
59
  'trigger_family: reload',
@@ -149,100 +70,32 @@ test('parses scalar/list values with spaces, quotes, and escapes without truncat
149
70
  ' - "double-quote \\"inside\\""',
150
71
  " - 'single-quote ''inside'''",
151
72
  'next_action: node gitnexus/dist/cli/index.js query --runtime-chain-verify on-demand "Reload NEON.Game.Graph.Nodes.Reloads"',
152
- ].join('\n'), 'utf-8');
153
- try {
154
- const registry = await loadRuleRegistry(repoPath);
155
- const rule = registry.activeRules[0];
156
- assert.equal(rule.id, 'demo.scalar-parser.v1');
157
- assert.deepEqual(rule.resource_types, ['asset ref', 'prefab ref']);
158
- assert.deepEqual(rule.guarantees, ['guarantee with spaces']);
159
- assert.deepEqual(rule.non_guarantees, ['double-quote "inside"', "single-quote 'inside'"]);
160
- assert.equal(rule.next_action, 'node gitnexus/dist/cli/index.js query --runtime-chain-verify on-demand "Reload NEON.Game.Graph.Nodes.Reloads"');
161
- }
162
- finally {
163
- await fs.rm(tempRoot, { recursive: true, force: true });
164
- }
165
- });
166
- test('rejects rule yaml when topology/closure/claims are missing', async () => {
167
- const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'gitnexus-runtime-claim-rules-'));
168
- const repoPath = path.join(tempRoot, 'repo');
169
- const rulesRoot = path.join(repoPath, '.gitnexus', 'rules');
170
- await fs.mkdir(path.join(rulesRoot, 'approved'), { recursive: true });
171
- await fs.writeFile(path.join(rulesRoot, 'catalog.json'), JSON.stringify({
172
- rules: [
173
- {
174
- id: 'demo.reload.rule.v2',
175
- version: '2.0.0',
176
- file: 'approved/demo.reload.rule.v2.yaml',
177
- },
178
- ],
179
- }), 'utf-8');
180
- await fs.writeFile(path.join(rulesRoot, 'approved', 'demo.reload.rule.v2.yaml'), [
181
- 'id: demo.reload.rule.v2',
182
- 'version: 2.0.0',
183
- 'trigger_family: reload',
184
- 'resource_types:',
185
- ' - asset',
186
- 'host_base_type:',
187
- ' - ReloadBase',
188
- 'required_hops:',
189
- ' - resource',
190
- 'guarantees:',
191
- ' - reload_chain_closed',
192
- 'non_guarantees:',
193
- ' - no_runtime_execution_guarantee',
194
- ].join('\n'), 'utf-8');
195
- try {
196
- await assert.rejects(() => loadRuleRegistry(repoPath), /topology|closure|claims/i);
197
- }
198
- finally {
199
- await fs.rm(tempRoot, { recursive: true, force: true });
200
- }
201
- });
202
- test('loads v2 verification bundle from explicit compiled path without catalog fallback', async () => {
203
- const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'gitnexus-runtime-claim-rules-'));
204
- const repoPath = path.join(tempRoot, 'repo');
205
- const compiledRoot = path.join(repoPath, '.gitnexus', 'rules', 'compiled');
206
- await fs.mkdir(compiledRoot, { recursive: true });
207
- await fs.writeFile(path.join(compiledRoot, 'verification_rules.v2.json'), JSON.stringify({
208
- bundle_version: '2.0.0',
209
- family: 'verification_rules',
210
- generated_at: new Date().toISOString(),
211
- rules: [
212
- {
213
- id: 'demo.bundle.rule.v2',
214
- version: '2.0.0',
215
- trigger_family: 'reload',
216
- resource_types: ['asset'],
217
- host_base_type: ['ReloadBase'],
218
- required_hops: ['resource', 'code_runtime'],
219
- guarantees: ['reload_chain_closed'],
220
- non_guarantees: ['no_runtime_execution'],
221
- next_action: 'gitnexus query "reload"',
222
- file_path: '.gitnexus/rules/compiled/verification_rules.v2.json',
223
- match: { trigger_tokens: ['reload'] },
224
- topology: [
225
- { hop: 'resource', from: { entity: 'resource' }, to: { entity: 'script' }, edge: { kind: 'binds_script' } },
226
- ],
227
- closure: {
228
- required_hops: ['resource', 'code_runtime'],
229
- failure_map: { missing_evidence: 'rule_matched_but_evidence_missing' },
230
- },
231
- claims: {
232
- guarantees: ['reload_chain_closed'],
233
- non_guarantees: ['no_runtime_execution'],
234
- next_action: 'gitnexus query "reload"',
235
- },
236
- },
237
- ],
238
- }, null, 2), 'utf-8');
239
- try {
240
- const registry = await loadRuleRegistry(repoPath);
241
- assert.equal(registry.activeRules[0].id, 'demo.bundle.rule.v2');
242
- assert.equal(registry.activeRules[0].version, '2.0.0');
243
- assert.deepEqual(registry.activeRules[0].required_hops, ['resource', 'code_runtime']);
244
- }
245
- finally {
246
- await fs.rm(tempRoot, { recursive: true, force: true });
247
- }
73
+ 'match:',
74
+ ' trigger_tokens:',
75
+ ' - reload',
76
+ 'closure:',
77
+ ' required_hops:',
78
+ ' - resource',
79
+ 'claims:',
80
+ ' guarantees:',
81
+ " - 'guarantee with spaces'",
82
+ ' non_guarantees:',
83
+ ' - "double-quote \\"inside\\""',
84
+ " - 'single-quote ''inside'''",
85
+ ' next_action: query "reload"',
86
+ 'topology:',
87
+ ' - hop: resource',
88
+ ' from:',
89
+ ' entity: resource',
90
+ ' to:',
91
+ ' entity: script',
92
+ ' edge:',
93
+ ' kind: binds_script',
94
+ ].join('\n');
95
+ const rule = parseRuleYaml(yaml, 'scalar.yaml');
96
+ assert.equal(rule.id, 'demo.scalar-parser.v1');
97
+ assert.deepEqual(rule.resource_types, ['asset ref', 'prefab ref']);
98
+ assert.deepEqual(rule.guarantees, ['guarantee with spaces']);
99
+ assert.deepEqual(rule.non_guarantees, ['double-quote "inside"', "single-quote 'inside'"]);
100
+ assert.equal(rule.next_action, 'query "reload"');
248
101
  });
package/dist/mcp/tools.js CHANGED
@@ -383,76 +383,6 @@ Output enforces unique-result policy and includes path+line evidence hops.`,
383
383
  required: ['target', 'goal'],
384
384
  },
385
385
  },
386
- {
387
- name: 'rule_lab_analyze',
388
- description: `Analyze one Rule Lab slice and emit anchor-backed candidates.jsonl.`,
389
- inputSchema: {
390
- type: 'object',
391
- properties: {
392
- run_id: { type: 'string', description: 'Rule Lab run id' },
393
- slice_id: { type: 'string', description: 'Rule Lab slice id' },
394
- repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
395
- },
396
- required: ['run_id', 'slice_id'],
397
- },
398
- },
399
- {
400
- name: 'rule_lab_review_pack',
401
- description: `Pack analyzed candidates into review cards with token budget enforcement.`,
402
- inputSchema: {
403
- type: 'object',
404
- properties: {
405
- run_id: { type: 'string', description: 'Rule Lab run id' },
406
- slice_id: { type: 'string', description: 'Rule Lab slice id' },
407
- max_tokens: { type: 'number', description: 'Token budget cap (default: 6000)', default: 6000 },
408
- repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
409
- },
410
- required: ['run_id', 'slice_id'],
411
- },
412
- },
413
- {
414
- name: 'rule_lab_curate',
415
- description: `Validate human-curated semantic closure input and persist curated artifacts for promotion.`,
416
- inputSchema: {
417
- type: 'object',
418
- properties: {
419
- run_id: { type: 'string', description: 'Rule Lab run id' },
420
- slice_id: { type: 'string', description: 'Rule Lab slice id' },
421
- input_path: { type: 'string', description: 'Absolute or repo-relative path to curation input JSON' },
422
- repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
423
- },
424
- required: ['run_id', 'slice_id', 'input_path'],
425
- },
426
- },
427
- {
428
- name: 'rule_lab_promote',
429
- description: `Promote curated candidates into approved YAML rules and upsert catalog.json entries.`,
430
- inputSchema: {
431
- type: 'object',
432
- properties: {
433
- run_id: { type: 'string', description: 'Rule Lab run id' },
434
- slice_id: { type: 'string', description: 'Rule Lab slice id' },
435
- version: { type: 'string', description: 'Promoted rule version (default: 1.0.0)', default: '1.0.0' },
436
- repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
437
- },
438
- required: ['run_id', 'slice_id'],
439
- },
440
- },
441
- {
442
- name: 'rule_lab_regress',
443
- description: `Evaluate Rule Lab precision/coverage gates and optionally persist a regression report.`,
444
- inputSchema: {
445
- type: 'object',
446
- properties: {
447
- precision: { type: 'number', description: 'Observed precision metric' },
448
- coverage: { type: 'number', description: 'Observed coverage metric' },
449
- probes_path: { type: 'string', description: 'Optional path to a JSON array of regression probes with bucket metadata' },
450
- run_id: { type: 'string', description: 'Optional run id for report naming' },
451
- repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
452
- },
453
- required: ['precision', 'coverage'],
454
- },
455
- },
456
386
  {
457
387
  name: 'impact',
458
388
  description: `Analyze the blast radius of changing a code symbol.
@@ -15,6 +15,7 @@ export interface RepoMeta {
15
15
  scopeRules?: string[];
16
16
  repoAlias?: string;
17
17
  embeddings?: boolean;
18
+ csharpDefineCsproj?: string;
18
19
  };
19
20
  stats?: {
20
21
  files?: number;
@@ -2,7 +2,6 @@ import { GraphNode, GraphRelationship, KnowledgeGraph } from '../core/graph/type
2
2
  import { CommunityDetectionResult } from '../core/ingestion/community-processor.js';
3
3
  import { ProcessDetectionResult } from '../core/ingestion/process-processor.js';
4
4
  import type { UnityResourceProcessingResult } from '../core/ingestion/unity-resource-processor.js';
5
- import type { UnityRuntimeBindingResult } from '../core/ingestion/unity-runtime-binding-rules.js';
6
5
  import type { ScopeSelectionDiagnostics } from '../core/ingestion/scope-filter.js';
7
6
  export type PipelinePhase = 'idle' | 'extracting' | 'structure' | 'parsing' | 'imports' | 'calls' | 'heritage' | 'communities' | 'processes' | 'enriching' | 'complete' | 'error';
8
7
  export interface PipelineProgress {
@@ -40,7 +39,6 @@ export interface PipelineResult {
40
39
  communityResult?: CommunityDetectionResult;
41
40
  processResult?: ProcessDetectionResult;
42
41
  unityResult?: UnityResourceProcessingResult;
43
- unityRuleBindingResult?: UnityRuntimeBindingResult;
44
42
  scopeDiagnostics?: ScopeSelectionDiagnostics;
45
43
  csharpPreprocDiagnostics?: CSharpPreprocDiagnostics;
46
44
  }
@@ -49,7 +47,6 @@ export interface PipelineRuntimeSummary {
49
47
  communityResult?: CommunityDetectionResult;
50
48
  processResult?: ProcessDetectionResult;
51
49
  unityResult?: UnityResourceProcessingResult;
52
- unityRuleBindingResult?: UnityRuntimeBindingResult;
53
50
  scopeDiagnostics?: ScopeSelectionDiagnostics;
54
51
  csharpPreprocDiagnostics?: CSharpPreprocDiagnostics;
55
52
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veewo/gitnexus",
3
- "version": "1.5.6",
3
+ "version": "1.5.8",
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",
@@ -60,73 +60,97 @@ $GN analyze
60
60
 
61
61
  Run from the project root. This parses all source files, builds the knowledge graph, writes it to `.gitnexus/`, and generates CLAUDE.md / AGENTS.md context files.
62
62
 
63
+ Analyze options are resolved with two-layer priority: **CLI arguments** > **stored options** in `meta.json.analyzeOptions`. On first run, pass CLI flags; they are persisted automatically for subsequent runs.
64
+
63
65
  | Flag | Effect |
64
66
  |------|--------|
65
67
  | `--force` | Force full re-index even if up to date |
68
+ | `--no-reuse-options` | Do not reuse stored analyze options from previous index |
66
69
  | `--embeddings` | Enable embedding generation (off by default) |
70
+ | `--extensions <list>` | Comma-separated file extensions (e.g. `.cs,.ts`) |
71
+ | `--scope <rules>` | Comma-separated scope path-prefix rules (e.g. `Assets/,Packages/com.veewo.*`) |
72
+ | `--repo-alias <name>` | Override indexed repository name with a stable alias |
73
+ | `--csharp-define-csproj <path>` | Load C# `DefineConstants` from `.csproj` for `#if` normalization |
67
74
  | `--skills` | Generate repo-specific skill files from detected communities |
75
+ | `-v, --verbose` | Enable verbose ingestion warnings |
68
76
 
69
- **Two mutually exclusive paths. Choose one per rebuild.**
77
+ **Option persistence:** `--extensions`, `--scope`, `--repo-alias`, `--embeddings`, and `--csharp-define-csproj` are automatically saved to `meta.json.analyzeOptions` after a successful run. On subsequent runs, these stored values are reused unless you pass new CLI flags or use `--no-reuse-options`.
70
78
 
71
- #### Path A: sync-manifest managed (recommended for Unity / monorepo)
79
+ #### Scope rules
72
80
 
73
- If `.gitnexus/sync-manifest.txt` exists, `analyze` **auto-uses** it when you do **not** pass `--scope-prefix` or `--scope-manifest`.
81
+ Scope rules control which files are included in the index. When no scope rules are stored, **all files** in the repo are indexed. Use `--scope` on first run to set scope rules; they are persisted automatically.
82
+
83
+ **Scope rule semantics:**
84
+ - Each rule is a **path prefix** — `Assets/` matches all files under `Assets/`
85
+ - Trailing `*` is a **wildcard prefix** — `Packages/com.veewo.*` matches `Packages/com.veewo.stat/...`
86
+ - No glob support: `Assets/**/*.cs` will not work
87
+ - Empty scope = full repo scan (all files)
74
88
 
75
89
  ```bash
76
- # Unity project with an existing manifest — this is the normal rebuild command
90
+ # Scope to specific directories
91
+ $GN analyze --force --scope "Assets/,Packages/"
92
+
93
+ # Wildcard scope
94
+ $GN analyze --force --scope "Assets/NEON/Code,Packages/com.veewo.*"
95
+
96
+ # No --scope = full repo (or reuse stored scope rules)
77
97
  $GN analyze --force
78
98
  ```
79
99
 
80
- The manifest controls scope rules, extensions, and repo alias. Example:
100
+ #### Unity project recommended parameters
81
101
 
82
- ```
83
- Assets/
84
- Packages/
85
- @extensions=.cs,.meta
86
- @repoAlias=neonspark-core
102
+ Unity projects benefit from a specific combination of parameters to ensure correct C# parsing and optimal scope:
103
+
104
+ ```bash
105
+ # Unity project — first-time index (recommended)
106
+ $GN analyze --force \
107
+ --extensions ".cs,.meta" \
108
+ --scope "Assets/,Packages/" \
109
+ --repo-alias <repo-alias> \
110
+ --csharp-define-csproj <path-to-Assembly-CSharp.csproj>
111
+
112
+ # Subsequent rebuilds (all options are reused automatically)
113
+ $GN analyze --force
87
114
  ```
88
115
 
89
- - Non-`@` lines = path-prefix scope rules
90
- - `@extensions=<csv>` = file extension filter
91
- - `@repoAlias=<name>` = stable repo alias
92
- - `@embeddings=<true|false>` = embedding toggle
116
+ | Parameter | Recommended value | Why |
117
+ |-----------|------------------|-----|
118
+ | `--extensions` | `.cs,.meta` | C# scripts + Unity `.meta` asset files for resource binding |
119
+ | `--scope` | `Assets/,Packages/` | Limit to Unity project directories; skip `Library/`, `Temp/`, `obj/` |
120
+ | `--csharp-define-csproj` | `path/to/Assembly-CSharp.csproj` | Normalize `#if` / `#elif` conditional compilation using project's `DefineConstants` |
121
+ | `--repo-alias` | e.g. `neonspark-core` | Stable alias for MCP repo lookup regardless of directory name |
93
122
 
94
- **Drift guard:** If you pass `--extensions` / `--repo-alias` / `--embeddings` while a manifest exists, CLI compares them. Use `--sync-manifest-policy` to control: `ask|update|keep|error` (default `ask`; non-TTY requires explicit policy).
123
+ **C# preprocessing detail:** Unity projects commonly use conditional compilation (`#if UNITY_EDITOR`, `#if NEON_DEBUG`, etc.). Without `--csharp-define-csproj`, tree-sitter parses each `#if` branch as-is, often producing incorrect AST for the active branch. The csproj path is persisted and reused automatically after first specification.
95
124
 
96
- **Do not mix Path A and Path B.** Passing `--scope-prefix` or `--extensions` when a manifest exists triggers the drift guard and may error out in non-TTY environments.
125
+ **Scope for large Unity repos:** For repos where only specific packages matter, narrow scope instead of indexing all of `Assets/`:
97
126
 
98
- #### Path B: manual CLI flags (first-time or simple projects)
127
+ ```bash
128
+ $GN analyze --force \
129
+ --scope "Assets/NEON/Code,Packages/com.veewo.*" \
130
+ --extensions ".cs,.meta" \
131
+ --repo-alias neonspark-core
132
+ ```
99
133
 
100
- Use when no sync-manifest exists:
134
+ #### Other project examples
101
135
 
102
136
  ```bash
103
- # Unity project, first-time index
104
- $GN analyze --force --extensions ".cs,.meta" --scope-prefix Assets/ --repo-alias neonspark-core
137
+ # Generic TypeScript project
138
+ $GN analyze --force --extensions ".ts,.tsx" --repo-alias my-project
105
139
 
106
- # Generic project
107
- $GN analyze --force --extensions ".ts,.tsx" --scope-prefix src/
140
+ # Subsequent rebuilds (stored options are reused automatically)
141
+ $GN analyze --force
108
142
  ```
109
143
 
110
- | Manual flag | Effect |
111
- |-------------|--------|
112
- | `--extensions <ext>` | Comma-separated file extensions |
113
- | `--scope-prefix <prefix>` | Add a path prefix rule (repeatable) |
114
- | `--scope-manifest <file>` | Read scope rules from a manifest file |
115
- | `--repo-alias <name>` | Override indexed repository name |
116
- | `--csharp-define-csproj <path>` | Load C# `DefineConstants` from `.csproj` for `#if` normalization |
117
-
118
- **C# preprocessing (Unity):** For projects with heavy conditional compilation, add `--csharp-define-csproj /path/to/Assembly-CSharp.csproj` (neonspark: `/Volumes/Shuttle/projects/neonspark/Assembly-CSharp.csproj`). Without it, C# files are parsed raw and tree-sitter may mishandle `#if` branches.
119
-
120
144
  #### Rebuild recovery — when analyze hangs or crashes
121
145
 
122
146
  If `analyze --force` hangs (no progress after 5+ minutes) or crashes leaving a corrupted index:
123
147
 
124
148
  ```bash
125
- # 1. Clean the corrupted index (preserves sync-manifest.txt)
149
+ # 1. Clean the corrupted index
126
150
  $GN clean --force
127
151
 
128
- # 2. Rebuild
129
- $GN analyze --force
152
+ # 2. Rebuild (re-specify CLI options since meta.json was deleted)
153
+ $GN analyze --force --extensions ".cs,.meta" --repo-alias neonspark-core
130
154
  ```
131
155
 
132
156
  **When to clean before rebuild:**
@@ -145,13 +169,13 @@ $GN status
145
169
 
146
170
  Shows whether the current repo has a GitNexus index, when it was last updated, and symbol/relationship counts. Use this to check if re-indexing is needed.
147
171
 
148
- ### clean — Delete the index (preserves config)
172
+ ### clean — Delete the index
149
173
 
150
174
  ```bash
151
175
  $GN clean --force
152
176
  ```
153
177
 
154
- Removes the GitNexus index (graph, CSVs, LadybugDB) from `.gitnexus/` while **preserving `sync-manifest.txt`** and other configuration files. Use this to recover from a corrupted index before re-indexing.
178
+ Removes the entire `.gitnexus/` directory (including `meta.json` and all index data). After cleaning, you must re-specify analyze options on the next `analyze` run since stored options are deleted.
155
179
 
156
180
  | Flag | Effect |
157
181
  | --------- | ------------------------------------------------- |
@@ -237,7 +261,7 @@ $GN unity-ui-trace "Assets/NEON/VeewoUI/Uxml/BarScreen/Patch/PatchItemPreview.ux
237
261
  - **"Not inside a git repository"**: Run from a directory inside a git repo
238
262
  - **Index is stale after re-analyzing**: Restart Claude Code to reload the MCP server
239
263
  - **Embeddings slow**: Omit `--embeddings` (it's off by default) or set `OPENAI_API_KEY` for faster API-based embedding
240
- - **`analyze --force` hangs or crashes**: Run `$GN clean --force` to remove the corrupted index (sync-manifest is preserved), then `$GN analyze --force` to rebuild. Common corruption signatures: `.gitnexus/csv/` exists but `relations.csv` is missing; `.gitnexus/lbug.wal` exists while `lbug` is only a few KB.
264
+ - **`analyze --force` hangs or crashes**: Run `$GN clean --force` to remove the corrupted index, then `$GN analyze --force` (with your CLI options) to rebuild. Common corruption signatures: `.gitnexus/csv/` exists but `relations.csv` is missing; `.gitnexus/lbug.wal` exists while `lbug` is only a few KB.
241
265
 
242
266
  ## Runtime-Chain Closure Guard
243
267
 
@@ -0,0 +1,6 @@
1
+ # This file is generated by gyp; do not edit.
2
+
3
+ export builddir_name ?= ./build/../../node_modules/node-addon-api/.
4
+ .PHONY: all
5
+ all:
6
+ $(MAKE) -C ../../tree-sitter-dart/build node_addon_api_except