@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,387 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
- import { getRuleLabPaths } from './paths.js';
4
- import { writeCompiledRuleBundle, loadCompiledRuleBundle } from './compiled-bundles.js';
5
- function quoteYaml(value) {
6
- const raw = String(value || '');
7
- if (/^[a-zA-Z0-9._-]+$/.test(raw))
8
- return raw;
9
- return `'${raw.replace(/'/g, "''")}'`;
10
- }
11
- function inferTriggerFamily(item) {
12
- const fromTitle = String(item.title || '').trim().split(/\s+/)[0];
13
- if (fromTitle)
14
- return fromTitle.toLowerCase();
15
- return 'runtime';
16
- }
17
- function unique(values) {
18
- return [...new Set(values.map((value) => String(value || '').trim()).filter(Boolean))];
19
- }
20
- function toComparableToken(value) {
21
- return String(value || '').trim().toLowerCase();
22
- }
23
- function isForbiddenPlaceholder(value) {
24
- const token = toComparableToken(value);
25
- return token === 'unknown' || token === 'todo' || token === 'tbd' || /<[^>]+>/.test(token);
26
- }
27
- function hasPlaceholderText(value) {
28
- const raw = String(value || '').trim();
29
- return !raw || /TODO|TBD|placeholder|<[^>]+>/i.test(raw);
30
- }
31
- function assertNoPlaceholderScope(values, field) {
32
- if (values.length === 0) {
33
- throw new Error(`promote lint failed: ${field} must be non-empty`);
34
- }
35
- if (values.some((entry) => isForbiddenPlaceholder(entry))) {
36
- throw new Error(`promote lint failed: unknown scope placeholder is forbidden (${field})`);
37
- }
38
- }
39
- function assertResolvedBindings(resourceBindings, ruleId) {
40
- if (!Array.isArray(resourceBindings) || resourceBindings.length === 0)
41
- return;
42
- const raw = JSON.stringify(resourceBindings);
43
- if (/UnknownClass|UnknownMethod|UnknownSource|UnknownTarget|TODO|TBD|placeholder|<[^>]+>/i.test(raw)) {
44
- throw new Error(`binding_unresolved: placeholder binding values are forbidden for rule ${ruleId}`);
45
- }
46
- }
47
- function requireEvidenceGuard(item, ruleId) {
48
- const steps = Array.isArray(item.confirmed_chain?.steps) ? item.confirmed_chain.steps : [];
49
- if (steps.length === 0) {
50
- throw new Error(`evidence_guard_failed: confirmed_chain.steps must be non-empty for rule ${ruleId}`);
51
- }
52
- for (let index = 0; index < steps.length; index += 1) {
53
- const step = steps[index];
54
- if (hasPlaceholderText(step.anchor)) {
55
- throw new Error(`evidence_guard_failed: confirmed_chain.steps[${index}].anchor invalid for rule ${ruleId}`);
56
- }
57
- if (hasPlaceholderText(step.snippet)) {
58
- throw new Error(`evidence_guard_failed: confirmed_chain.steps[${index}].snippet invalid for rule ${ruleId}`);
59
- }
60
- }
61
- }
62
- function isExactPairEventDelegateItem(item) {
63
- const triggerTokens = Array.isArray(item.match?.trigger_tokens)
64
- ? item.match?.trigger_tokens || []
65
- : [];
66
- const hasEventDelegateTrigger = triggerTokens.some((token) => toComparableToken(token) === 'event_delegate');
67
- if (!hasEventDelegateTrigger)
68
- return false;
69
- const hasCodeRuntimeTopology = Array.isArray(item.topology)
70
- && item.topology.some((hop) => toComparableToken(hop.hop) === 'code_runtime');
71
- const hasEvidence = Array.isArray(item.confirmed_chain?.steps) && item.confirmed_chain.steps.length > 0;
72
- return hasCodeRuntimeTopology && hasEvidence;
73
- }
74
- function requireBindingGuard(item, ruleId) {
75
- const bindings = item.resource_bindings;
76
- if (isExactPairEventDelegateItem(item) && (!Array.isArray(bindings) || bindings.length === 0)) {
77
- throw new Error(`binding_unresolved: exact_pair_binding_missing for rule ${ruleId}`);
78
- }
79
- assertResolvedBindings(bindings, ruleId);
80
- }
81
- function toDraftFromCurated(item) {
82
- const triggerTokens = unique(item.match?.trigger_tokens || [inferTriggerFamily(item)]);
83
- const topology = Array.isArray(item.topology) && item.topology.length > 0
84
- ? item.topology
85
- : item.confirmed_chain.steps.map((step) => ({
86
- hop: String(step.hop_type || 'resource'),
87
- from: { entity: 'resource' },
88
- to: { entity: 'script' },
89
- edge: { kind: 'binds_script' },
90
- }));
91
- const requiredHops = unique(item.closure?.required_hops || topology.map((step) => step.hop));
92
- const failureMap = item.closure?.failure_map && Object.keys(item.closure.failure_map).length > 0
93
- ? item.closure.failure_map
94
- : { missing_evidence: 'rule_matched_but_evidence_missing' };
95
- const guarantees = unique(item.claims?.guarantees || item.guarantees);
96
- const nonGuarantees = unique(item.claims?.non_guarantees || item.non_guarantees);
97
- const nextAction = String(item.claims?.next_action || '').trim() || 'gitnexus query "runtime"';
98
- return {
99
- id: String(item.rule_id || item.id || '').trim(),
100
- version: '2.0.0',
101
- match: {
102
- trigger_tokens: triggerTokens,
103
- symbol_kind: item.match?.symbol_kind || [],
104
- module_scope: item.match?.module_scope || [],
105
- resource_types: unique(item.match?.resource_types || []),
106
- host_base_type: unique(item.match?.host_base_type || []),
107
- },
108
- topology,
109
- closure: {
110
- required_hops: requiredHops,
111
- failure_map: failureMap,
112
- },
113
- claims: {
114
- guarantees,
115
- non_guarantees: nonGuarantees,
116
- next_action: nextAction,
117
- },
118
- ...(Array.isArray(item.resource_bindings)
119
- ? { resource_bindings: item.resource_bindings }
120
- : {}),
121
- };
122
- }
123
- function compileRule(ruleId, version, draft) {
124
- const triggerFamily = String(draft.match.trigger_tokens[0] || '').trim() || 'runtime';
125
- const resourceTypes = unique(draft.match.resource_types || []);
126
- const hostBaseType = unique(draft.match.host_base_type || []);
127
- if (resourceTypes.length === 0) {
128
- resourceTypes.push('unspecified_resource');
129
- }
130
- if (hostBaseType.length === 0) {
131
- hostBaseType.push('unspecified_host');
132
- }
133
- const requiredHops = unique(draft.closure.required_hops);
134
- const guarantees = unique(draft.claims.guarantees);
135
- const nonGuarantees = unique(draft.claims.non_guarantees);
136
- const nextAction = String(draft.claims.next_action || '').trim() || 'gitnexus query "runtime"';
137
- assertNoPlaceholderScope(resourceTypes, 'resource_types');
138
- assertNoPlaceholderScope(hostBaseType, 'host_base_type');
139
- assertResolvedBindings(draft.resource_bindings, ruleId);
140
- return {
141
- id: ruleId,
142
- version,
143
- trigger_family: triggerFamily,
144
- resource_types: resourceTypes,
145
- host_base_type: hostBaseType,
146
- required_hops: requiredHops,
147
- guarantees,
148
- non_guarantees: nonGuarantees,
149
- next_action: nextAction,
150
- match: draft.match,
151
- topology: draft.topology,
152
- closure: draft.closure,
153
- claims: draft.claims,
154
- ...(draft.resource_bindings ? { resource_bindings: draft.resource_bindings } : {}),
155
- ...(draft.lifecycle_overrides ? { lifecycle_overrides: draft.lifecycle_overrides } : {}),
156
- };
157
- }
158
- function toStageAwareCompiledRule(rule, relativeFile) {
159
- return {
160
- id: rule.id,
161
- version: rule.version,
162
- trigger_family: rule.trigger_family,
163
- trigger_tokens: [...rule.match.trigger_tokens],
164
- resource_types: [...rule.resource_types],
165
- host_base_type: [...rule.host_base_type],
166
- required_hops: [...rule.required_hops],
167
- guarantees: [...rule.guarantees],
168
- non_guarantees: [...rule.non_guarantees],
169
- next_action: rule.next_action,
170
- file_path: relativeFile,
171
- match: rule.match,
172
- topology: rule.topology,
173
- closure: rule.closure,
174
- claims: rule.claims,
175
- ...(rule.resource_bindings ? { resource_bindings: rule.resource_bindings } : {}),
176
- ...(rule.lifecycle_overrides ? { lifecycle_overrides: rule.lifecycle_overrides } : {}),
177
- };
178
- }
179
- function pushList(lines, key, values, indent = '') {
180
- lines.push(`${indent}${key}:`);
181
- values.forEach((value) => lines.push(`${indent} - ${quoteYaml(value)}`));
182
- }
183
- function renderObjectLines(lines, object, indent = '') {
184
- const entries = Object.entries(object || {});
185
- for (const [key, value] of entries) {
186
- const scalar = typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'
187
- ? String(value)
188
- : JSON.stringify(value);
189
- lines.push(`${indent}${key}: ${quoteYaml(scalar)}`);
190
- }
191
- }
192
- function buildRuleYaml(rule) {
193
- const lines = [
194
- `id: ${quoteYaml(rule.id)}`,
195
- `version: ${quoteYaml(rule.version)}`,
196
- ...(rule.family ? [`family: ${quoteYaml(rule.family)}`] : []),
197
- `trigger_family: ${quoteYaml(rule.trigger_family)}`,
198
- ];
199
- pushList(lines, 'resource_types', rule.resource_types);
200
- pushList(lines, 'host_base_type', rule.host_base_type);
201
- pushList(lines, 'required_hops', rule.required_hops);
202
- pushList(lines, 'guarantees', rule.guarantees);
203
- pushList(lines, 'non_guarantees', rule.non_guarantees);
204
- lines.push(`next_action: ${quoteYaml(rule.next_action)}`);
205
- lines.push('match:');
206
- pushList(lines, 'trigger_tokens', rule.match.trigger_tokens, ' ');
207
- if (Array.isArray(rule.match.symbol_kind) && rule.match.symbol_kind.length > 0) {
208
- pushList(lines, 'symbol_kind', rule.match.symbol_kind, ' ');
209
- }
210
- if (Array.isArray(rule.match.module_scope) && rule.match.module_scope.length > 0) {
211
- pushList(lines, 'module_scope', rule.match.module_scope, ' ');
212
- }
213
- if (Array.isArray(rule.match.resource_types) && rule.match.resource_types.length > 0) {
214
- pushList(lines, 'resource_types', rule.match.resource_types, ' ');
215
- }
216
- if (Array.isArray(rule.match.host_base_type) && rule.match.host_base_type.length > 0) {
217
- pushList(lines, 'host_base_type', rule.match.host_base_type, ' ');
218
- }
219
- lines.push('topology:');
220
- for (const hop of rule.topology) {
221
- lines.push(` - hop: ${quoteYaml(hop.hop)}`);
222
- lines.push(' from:');
223
- renderObjectLines(lines, hop.from || {}, ' ');
224
- lines.push(' to:');
225
- renderObjectLines(lines, hop.to || {}, ' ');
226
- lines.push(' edge:');
227
- lines.push(` kind: ${quoteYaml(String(hop.edge?.kind || 'calls'))}`);
228
- if (hop.constraints && Object.keys(hop.constraints).length > 0) {
229
- lines.push(' constraints:');
230
- renderObjectLines(lines, hop.constraints, ' ');
231
- }
232
- }
233
- lines.push('closure:');
234
- pushList(lines, 'required_hops', rule.closure.required_hops, ' ');
235
- lines.push(' failure_map:');
236
- for (const [key, value] of Object.entries(rule.closure.failure_map || {})) {
237
- lines.push(` ${quoteYaml(key)}: ${quoteYaml(String(value || 'rule_matched_but_evidence_missing'))}`);
238
- }
239
- lines.push('claims:');
240
- pushList(lines, 'guarantees', rule.claims.guarantees, ' ');
241
- pushList(lines, 'non_guarantees', rule.claims.non_guarantees, ' ');
242
- lines.push(` next_action: ${quoteYaml(rule.claims.next_action)}`);
243
- if (rule.resource_bindings && rule.resource_bindings.length > 0) {
244
- lines.push('resource_bindings:');
245
- for (const binding of rule.resource_bindings) {
246
- lines.push(` - kind: ${binding.kind}`);
247
- if (binding.ref_field_pattern)
248
- lines.push(` ref_field_pattern: ${quoteYaml(binding.ref_field_pattern)}`);
249
- if (binding.target_entry_points?.length)
250
- pushList(lines, 'target_entry_points', binding.target_entry_points, ' ');
251
- if (binding.host_class_pattern)
252
- lines.push(` host_class_pattern: ${quoteYaml(binding.host_class_pattern)}`);
253
- if (binding.field_name)
254
- lines.push(` field_name: ${quoteYaml(binding.field_name)}`);
255
- if (binding.loader_methods?.length)
256
- pushList(lines, 'loader_methods', binding.loader_methods, ' ');
257
- if (binding.scene_name)
258
- lines.push(` scene_name: ${quoteYaml(binding.scene_name)}`);
259
- if (binding.source_class_pattern)
260
- lines.push(` source_class_pattern: ${quoteYaml(binding.source_class_pattern)}`);
261
- if (binding.source_method)
262
- lines.push(` source_method: ${quoteYaml(binding.source_method)}`);
263
- if (binding.target_class_pattern)
264
- lines.push(` target_class_pattern: ${quoteYaml(binding.target_class_pattern)}`);
265
- if (binding.target_method)
266
- lines.push(` target_method: ${quoteYaml(binding.target_method)}`);
267
- }
268
- }
269
- if (rule.lifecycle_overrides) {
270
- lines.push('lifecycle_overrides:');
271
- if (rule.lifecycle_overrides.additional_entry_points?.length) {
272
- pushList(lines, 'additional_entry_points', rule.lifecycle_overrides.additional_entry_points, ' ');
273
- }
274
- if (rule.lifecycle_overrides.scope) {
275
- lines.push(` scope: ${quoteYaml(rule.lifecycle_overrides.scope)}`);
276
- }
277
- }
278
- return `${lines.join('\n')}\n`;
279
- }
280
- async function readCatalog(catalogPath) {
281
- try {
282
- const raw = await fs.readFile(catalogPath, 'utf-8');
283
- const parsed = JSON.parse(raw);
284
- return {
285
- version: Number(parsed.version || 1),
286
- rules: Array.isArray(parsed.rules) ? parsed.rules : [],
287
- };
288
- }
289
- catch (error) {
290
- if (error?.code === 'ENOENT') {
291
- return { version: 1, rules: [] };
292
- }
293
- throw error;
294
- }
295
- }
296
- async function fileExists(filePath) {
297
- try {
298
- await fs.access(filePath);
299
- return true;
300
- }
301
- catch (error) {
302
- if (error?.code === 'ENOENT')
303
- return false;
304
- throw error;
305
- }
306
- }
307
- export async function promoteCuratedRules(input) {
308
- const normalizedRepoPath = path.resolve(input.repoPath);
309
- const paths = getRuleLabPaths(normalizedRepoPath, input.runId, input.sliceId);
310
- const version = String(input.version || '1.0.0');
311
- const curatedRaw = await fs.readFile(paths.curatedPath, 'utf-8');
312
- const curatedDoc = JSON.parse(curatedRaw);
313
- const curatedItems = Array.isArray(curatedDoc.curated) ? curatedDoc.curated : [];
314
- if (curatedItems.length === 0) {
315
- throw new Error('No curated candidates available for promotion');
316
- }
317
- let dslDraftFromCurate;
318
- try {
319
- const dslDraftRaw = await fs.readFile(path.join(path.dirname(paths.curatedPath), 'dsl-draft.json'), 'utf-8');
320
- dslDraftFromCurate = JSON.parse(dslDraftRaw);
321
- }
322
- catch (error) {
323
- if (error?.code !== 'ENOENT')
324
- throw error;
325
- }
326
- const catalogPath = path.join(paths.rulesRoot, 'catalog.json');
327
- const catalog = await readCatalog(catalogPath);
328
- const promotedFiles = [];
329
- const compiledRules = [];
330
- await fs.mkdir(paths.promotedRoot, { recursive: true });
331
- for (const item of curatedItems) {
332
- const ruleId = String(item.rule_id || item.id || '').trim();
333
- if (!ruleId) {
334
- throw new Error('curated item missing rule id');
335
- }
336
- requireEvidenceGuard(item, ruleId);
337
- requireBindingGuard(item, ruleId);
338
- if (catalog.rules.some((entry) => entry.id === ruleId)) {
339
- throw new Error(`duplicate_rule_id: ${ruleId} already exists in catalog`);
340
- }
341
- const relativeFile = path.join('approved', `${ruleId}.yaml`).split(path.sep).join('/');
342
- const absoluteFile = path.join(paths.rulesRoot, relativeFile);
343
- if (await fileExists(absoluteFile)) {
344
- throw new Error(`duplicate_rule_id: ${ruleId} already exists at ${relativeFile}`);
345
- }
346
- const draft = dslDraftFromCurate && curatedItems.length === 1
347
- ? { ...dslDraftFromCurate, id: ruleId, version }
348
- : { ...toDraftFromCurated(item), id: ruleId, version };
349
- const compiledRule = compileRule(ruleId, version, draft);
350
- const yaml = buildRuleYaml(compiledRule);
351
- await fs.writeFile(absoluteFile, yaml, 'utf-8');
352
- promotedFiles.push(absoluteFile);
353
- compiledRules.push(toStageAwareCompiledRule(compiledRule, relativeFile));
354
- const nextEntry = {
355
- id: ruleId,
356
- version,
357
- enabled: true,
358
- file: relativeFile,
359
- ...(compiledRule.family ? { family: compiledRule.family } : {}),
360
- };
361
- catalog.rules.push(nextEntry);
362
- }
363
- await fs.mkdir(path.dirname(catalogPath), { recursive: true });
364
- await fs.writeFile(catalogPath, `${JSON.stringify(catalog, null, 2)}\n`, 'utf-8');
365
- const mergeCompiledRules = async (family) => {
366
- const existing = await loadCompiledRuleBundle(normalizedRepoPath, family, paths.rulesRoot);
367
- const merged = new Map();
368
- for (const rule of existing?.rules || []) {
369
- merged.set(rule.id, rule);
370
- }
371
- for (const rule of compiledRules) {
372
- merged.set(rule.id, rule);
373
- }
374
- return writeCompiledRuleBundle(paths.rulesRoot, family, [...merged.values()]);
375
- };
376
- const compiledPaths = {
377
- analyze_rules: await mergeCompiledRules('analyze_rules'),
378
- retrieval_rules: await mergeCompiledRules('retrieval_rules'),
379
- verification_rules: await mergeCompiledRules('verification_rules'),
380
- };
381
- return {
382
- catalog,
383
- promotedFiles,
384
- compiledPaths,
385
- paths,
386
- };
387
- }
@@ -1 +0,0 @@
1
- export {};