@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,165 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
- import { getRuleLabPaths } from './paths.js';
4
- function estimateTokens(value) {
5
- return Math.ceil(JSON.stringify(value).length / 4);
6
- }
7
- function parseCandidates(raw) {
8
- return raw
9
- .split(/\r?\n/)
10
- .map((line) => line.trim())
11
- .filter(Boolean)
12
- .map((line) => JSON.parse(line));
13
- }
14
- function unique(values) {
15
- return [...new Set(values.map((value) => String(value || '').trim()).filter(Boolean))];
16
- }
17
- function mergeFailureMaps(candidates) {
18
- const out = {};
19
- for (const candidate of candidates) {
20
- const failureMap = candidate.closure?.failure_map || {};
21
- for (const [key, value] of Object.entries(failureMap)) {
22
- if (String(key || '').trim() && String(value || '').trim()) {
23
- out[key] = value;
24
- }
25
- }
26
- }
27
- return out;
28
- }
29
- function collectRequiredHops(candidates) {
30
- const fromClosure = candidates.flatMap((candidate) => {
31
- const closure = candidate.closure;
32
- return Array.isArray(closure?.required_hops) ? closure.required_hops : [];
33
- });
34
- if (fromClosure.length > 0)
35
- return unique(fromClosure);
36
- return unique(candidates.flatMap((candidate) => (candidate.topology || []).map((hop) => hop.hop)));
37
- }
38
- function collectClaims(candidates) {
39
- const guarantees = unique(candidates.flatMap((candidate) => {
40
- const claims = candidate.claims;
41
- return Array.isArray(claims?.guarantees) ? claims.guarantees : [];
42
- }));
43
- const nonGuarantees = unique(candidates.flatMap((candidate) => {
44
- const claims = candidate.claims;
45
- return Array.isArray(claims?.non_guarantees) ? claims.non_guarantees : [];
46
- }));
47
- return {
48
- guarantees,
49
- non_guarantees: nonGuarantees,
50
- };
51
- }
52
- function collectDraftRuleIds(candidates) {
53
- return unique(candidates.map((candidate) => String(candidate.draft_rule_id || '').trim()).filter(Boolean));
54
- }
55
- function collectAggregationModes(candidates) {
56
- return unique(candidates.map((candidate) => String(candidate.aggregation_mode || '').trim()).filter(Boolean));
57
- }
58
- function collectBindingKinds(candidates) {
59
- return unique(candidates.map((candidate) => String(candidate.binding_kind || '').trim()).filter(Boolean));
60
- }
61
- function buildCards(candidates) {
62
- const cards = [];
63
- const chunkSize = 4;
64
- for (let i = 0; i < candidates.length; i += chunkSize) {
65
- const chunk = candidates.slice(i, i + chunkSize);
66
- const claims = collectClaims(chunk);
67
- cards.push({
68
- card_id: `card-${Math.floor(i / chunkSize) + 1}`,
69
- title: `Rule Lab Card ${Math.floor(i / chunkSize) + 1}`,
70
- candidate_ids: chunk.map((item) => item.id),
71
- decision_inputs: {
72
- required_hops: collectRequiredHops(chunk),
73
- failure_map: mergeFailureMaps(chunk),
74
- guarantees: claims.guarantees,
75
- non_guarantees: claims.non_guarantees,
76
- draft_rule_ids: collectDraftRuleIds(chunk),
77
- aggregation_modes: collectAggregationModes(chunk),
78
- binding_kinds: collectBindingKinds(chunk),
79
- },
80
- });
81
- }
82
- return cards;
83
- }
84
- function renderReviewPack(meta, cards) {
85
- const lines = [];
86
- lines.push('# Rule Lab Review Pack');
87
- lines.push('');
88
- lines.push('## Meta');
89
- lines.push(`- token_budget: ${meta.token_budget}`);
90
- lines.push(`- token_budget_estimate: ${meta.token_budget_estimate}`);
91
- lines.push(`- truncated: ${meta.truncated}`);
92
- lines.push(`- total_candidates: ${meta.total_candidates}`);
93
- lines.push(`- included_candidates: ${meta.included_candidates}`);
94
- lines.push('');
95
- for (const card of cards) {
96
- lines.push(`## ${card.title}`);
97
- lines.push(`- card_id: ${card.card_id}`);
98
- lines.push(`- candidate_ids: ${card.candidate_ids.join(', ')}`);
99
- lines.push(`- required_hops: ${card.decision_inputs.required_hops.join(', ')}`);
100
- lines.push(`- guarantees: ${card.decision_inputs.guarantees.join(', ')}`);
101
- lines.push(`- non_guarantees: ${card.decision_inputs.non_guarantees.join(', ')}`);
102
- lines.push(`- draft_rule_ids: ${card.decision_inputs.draft_rule_ids.join(', ')}`);
103
- lines.push(`- aggregation_modes: ${card.decision_inputs.aggregation_modes.join(', ')}`);
104
- lines.push(`- binding_kinds: ${card.decision_inputs.binding_kinds.join(', ')}`);
105
- lines.push(`- failure_map: ${JSON.stringify(card.decision_inputs.failure_map)}`);
106
- lines.push('');
107
- }
108
- return `${lines.join('\n')}\n`;
109
- }
110
- function isENOENT(error) {
111
- return typeof error === 'object' && error !== null && error.code === 'ENOENT';
112
- }
113
- function sleep(ms) {
114
- return new Promise((resolve) => setTimeout(resolve, ms));
115
- }
116
- async function readCandidatesFileWithRetry(candidatesPath, analyzeCommandHint, timeoutMs = 3000, intervalMs = 100) {
117
- const deadline = Date.now() + timeoutMs;
118
- while (true) {
119
- try {
120
- return await fs.readFile(candidatesPath, 'utf-8');
121
- }
122
- catch (error) {
123
- if (!isENOENT(error))
124
- throw error;
125
- if (Date.now() >= deadline) {
126
- throw new Error(`Missing candidates file for review-pack: ${candidatesPath}\n` +
127
- `Run analyze first and wait for completion, then retry review-pack.\n` +
128
- `Suggested command: ${analyzeCommandHint}`);
129
- }
130
- await sleep(intervalMs);
131
- }
132
- }
133
- }
134
- export async function buildReviewPack(input) {
135
- const normalizedRepoPath = path.resolve(input.repoPath);
136
- const paths = getRuleLabPaths(normalizedRepoPath, input.runId, input.sliceId);
137
- const analyzeCommandHint = `gitnexus rule-lab analyze --repo-path "${normalizedRepoPath}" --run-id "${input.runId}" --slice-id "${input.sliceId}"`;
138
- const raw = await readCandidatesFileWithRetry(paths.candidatesPath, analyzeCommandHint);
139
- const candidates = parseCandidates(raw);
140
- const included = [];
141
- let tokenEstimate = 0;
142
- for (const candidate of candidates) {
143
- const nextTokens = estimateTokens(candidate);
144
- if (tokenEstimate + nextTokens > input.maxTokens) {
145
- break;
146
- }
147
- included.push(candidate);
148
- tokenEstimate += nextTokens;
149
- }
150
- const meta = {
151
- token_budget: input.maxTokens,
152
- token_budget_estimate: tokenEstimate,
153
- truncated: included.length < candidates.length,
154
- total_candidates: candidates.length,
155
- included_candidates: included.length,
156
- };
157
- const cards = buildCards(included);
158
- await fs.mkdir(path.dirname(paths.reviewCardsPath), { recursive: true });
159
- await fs.writeFile(paths.reviewCardsPath, renderReviewPack(meta, cards), 'utf-8');
160
- return {
161
- paths,
162
- meta,
163
- cards,
164
- };
165
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,116 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import fs from 'node:fs/promises';
3
- import os from 'node:os';
4
- import path from 'node:path';
5
- import { buildReviewPack } from './review-pack.js';
6
- describe('rule-lab review-pack', () => {
7
- it('splits cards to keep token budget <= 6000', async () => {
8
- const repoRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'rule-lab-review-pack-'));
9
- const sliceDir = path.join(repoRoot, '.gitnexus', 'rules', 'lab', 'runs', 'run-x', 'slices', 'slice-a');
10
- await fs.mkdir(sliceDir, { recursive: true });
11
- const candidate = {
12
- id: 'cand-1',
13
- title: 'reload candidate',
14
- topology: [
15
- {
16
- hop: 'resource',
17
- from: { entity: 'resource' },
18
- to: { entity: 'script' },
19
- edge: { kind: 'binds_script' },
20
- },
21
- ],
22
- closure: {
23
- required_hops: ['resource'],
24
- failure_map: { missing_evidence: 'rule_matched_but_evidence_missing' },
25
- },
26
- claims: {
27
- guarantees: ['reload_chain_closed'],
28
- non_guarantees: ['no_runtime_execution'],
29
- },
30
- evidence: {
31
- hops: [
32
- { hop_type: 'resource', anchor: 'Assets/Example.prefab:42', snippet: 'ReloadGraph' },
33
- ],
34
- },
35
- };
36
- const lines = Array.from({ length: 12 }).map((_, i) => JSON.stringify({ ...candidate, id: `cand-${i}` }));
37
- await fs.writeFile(path.join(sliceDir, 'candidates.jsonl'), `${lines.join('\n')}\n`, 'utf-8');
38
- const out = await buildReviewPack({ repoPath: repoRoot, runId: 'run-x', sliceId: 'slice-a', maxTokens: 6000 });
39
- expect(out.meta.token_budget_estimate).toBeLessThanOrEqual(6000);
40
- expect(out.meta.truncated || out.cards.length > 0).toBe(true);
41
- expect(out.cards[0]).toHaveProperty('decision_inputs.required_hops');
42
- expect(out.cards[0]).toHaveProperty('decision_inputs.failure_map');
43
- expect(out.cards[0]).toHaveProperty('decision_inputs.guarantees');
44
- expect(out.cards[0]).toHaveProperty('decision_inputs.non_guarantees');
45
- const persisted = await fs.readFile(out.paths.reviewCardsPath, 'utf-8');
46
- expect(persisted).toContain('token_budget_estimate');
47
- await fs.rm(repoRoot, { recursive: true, force: true });
48
- });
49
- it('shows actionable guidance when candidates are missing', async () => {
50
- const repoRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'rule-lab-review-pack-missing-'));
51
- const sliceDir = path.join(repoRoot, '.gitnexus', 'rules', 'lab', 'runs', 'run-y', 'slices', 'slice-b');
52
- await fs.mkdir(sliceDir, { recursive: true });
53
- const err = await buildReviewPack({ repoPath: repoRoot, runId: 'run-y', sliceId: 'slice-b', maxTokens: 6000 })
54
- .then(() => null)
55
- .catch((error) => error);
56
- expect(err).toBeTruthy();
57
- expect(String(err?.message || '')).toMatch(/Missing candidates file for review-pack/);
58
- expect(String(err?.message || '')).toMatch(/rule-lab analyze --repo-path/);
59
- await fs.rm(repoRoot, { recursive: true, force: true });
60
- });
61
- it('waits briefly for candidates to avoid analyze/review-pack races', async () => {
62
- const repoRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'rule-lab-review-pack-race-'));
63
- const sliceDir = path.join(repoRoot, '.gitnexus', 'rules', 'lab', 'runs', 'run-z', 'slices', 'slice-c');
64
- await fs.mkdir(sliceDir, { recursive: true });
65
- const candidatesPath = path.join(sliceDir, 'candidates.jsonl');
66
- const line = JSON.stringify({
67
- id: 'cand-race',
68
- title: 'race candidate',
69
- topology: [{ hop: 'resource', from: { entity: 'resource' }, to: { entity: 'script' }, edge: { kind: 'binds_script' } }],
70
- evidence: { hops: [{ hop_type: 'resource', anchor: 'Assets/Test.prefab:1', snippet: 'Race' }] },
71
- });
72
- const delayedWrite = new Promise((resolve, reject) => {
73
- setTimeout(() => {
74
- fs.writeFile(candidatesPath, `${line}\n`, 'utf-8').then(() => resolve()).catch(reject);
75
- }, 150);
76
- });
77
- const out = await buildReviewPack({ repoPath: repoRoot, runId: 'run-z', sliceId: 'slice-c', maxTokens: 6000 });
78
- await delayedWrite;
79
- expect(out.meta.total_candidates).toBe(1);
80
- await fs.rm(repoRoot, { recursive: true, force: true });
81
- });
82
- it('renders decision inputs without lineage-only fields', async () => {
83
- const repoRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'rule-lab-review-pack-direct-'));
84
- const sliceDir = path.join(repoRoot, '.gitnexus', 'rules', 'lab', 'runs', 'run-h', 'slices', 'slice-h');
85
- await fs.mkdir(sliceDir, { recursive: true });
86
- const rows = [
87
- {
88
- id: 'proposal-1',
89
- title: 'event_delegate proposal accepted-a',
90
- proposal_kind: 'per_anchor_rule',
91
- aggregation_mode: 'per_anchor_rules',
92
- draft_rule_id: 'unity.event.netplayer-gameover-syncvar-hook-ondeadchange.v1',
93
- binding_kind: 'method_triggers_method',
94
- topology: [{ hop: 'code_runtime', from: { entity: 'script' }, to: { entity: 'runtime' }, edge: { kind: 'calls' } }],
95
- evidence: { hops: [{ hop_type: 'code_runtime', anchor: 'Assets/A.cs:1', snippet: 'A' }] },
96
- },
97
- {
98
- id: 'proposal-2',
99
- title: 'event_delegate proposal accepted-b',
100
- proposal_kind: 'per_anchor_rule',
101
- aggregation_mode: 'per_anchor_rules',
102
- draft_rule_id: 'unity.event.mirrorbattlemgr-createnetplayer-syncvar-hook-changeroomgrid.v1',
103
- binding_kind: 'method_triggers_method',
104
- topology: [{ hop: 'code_runtime', from: { entity: 'script' }, to: { entity: 'runtime' }, edge: { kind: 'calls' } }],
105
- evidence: { hops: [{ hop_type: 'code_runtime', anchor: 'Assets/B.cs:2', snippet: 'B' }] },
106
- },
107
- ];
108
- await fs.writeFile(path.join(sliceDir, 'candidates.jsonl'), `${rows.map((row) => JSON.stringify(row)).join('\n')}\n`, 'utf-8');
109
- const out = await buildReviewPack({ repoPath: repoRoot, runId: 'run-h', sliceId: 'slice-h', maxTokens: 6000 });
110
- const persisted = await fs.readFile(out.paths.reviewCardsPath, 'utf-8');
111
- expect(persisted).not.toContain('Handoff Summary');
112
- expect(persisted).not.toContain('source_gap_candidate_ids');
113
- expect(persisted).toContain('draft_rule_ids: unity.event.netplayer-gameover-syncvar-hook-ondeadchange.v1, unity.event.mirrorbattlemgr-createnetplayer-syncvar-hook-changeroomgrid.v1');
114
- await fs.rm(repoRoot, { recursive: true, force: true });
115
- });
116
- });
@@ -1,135 +0,0 @@
1
- export type RuleLabScope = 'full' | 'diff';
2
- export type RuntimeClaimFailureReason = 'rule_not_matched' | 'rule_matched_but_evidence_missing' | 'rule_matched_but_verification_failed' | 'gate_disabled';
3
- export interface RuleLabSlice {
4
- id: string;
5
- trigger_family: string;
6
- resource_types: string[];
7
- host_base_type: string[];
8
- required_hops?: string[];
9
- exact_pairs?: RuleLabExactPair[];
10
- }
11
- export interface RuleLabManifest {
12
- run_id: string;
13
- repo_path: string;
14
- scope: RuleLabScope;
15
- generated_at: string;
16
- slices: RuleLabSlice[];
17
- next_actions: string[];
18
- stages: string[];
19
- }
20
- export interface RuleLabCandidateHop {
21
- hop_type: string;
22
- anchor: string;
23
- snippet: string;
24
- }
25
- export interface RuleLabCandidate {
26
- id: string;
27
- title: string;
28
- rule_hint?: string;
29
- proposal_kind?: 'per_anchor_rule' | 'aggregate_rule';
30
- source_slice_id?: string;
31
- aggregation_mode?: 'per_anchor_rules' | 'aggregate_single_rule';
32
- binding_kind?: string;
33
- draft_rule_id?: string;
34
- topology?: Array<{
35
- hop: string;
36
- from: Record<string, unknown>;
37
- to: Record<string, unknown>;
38
- edge: {
39
- kind: string;
40
- };
41
- constraints?: Record<string, unknown>;
42
- }>;
43
- stats?: {
44
- covered: number;
45
- total: number;
46
- conflicts: number;
47
- coverage_rate: number;
48
- conflict_rate: number;
49
- };
50
- counter_examples?: Array<{
51
- reason: string;
52
- missing_hop?: string;
53
- evidence_anchor?: string;
54
- }>;
55
- closure?: {
56
- required_hops: string[];
57
- failure_map: Record<string, RuntimeClaimFailureReason | string>;
58
- };
59
- claims?: {
60
- guarantees: string[];
61
- non_guarantees: string[];
62
- next_action: string;
63
- };
64
- proposal_evidence_keys?: string[];
65
- exact_pair?: RuleLabExactPair;
66
- evidence: {
67
- hops: RuleLabCandidateHop[];
68
- };
69
- }
70
- export interface RuleLabExactPairAnchor {
71
- file: string;
72
- line?: number;
73
- symbol?: string;
74
- }
75
- export interface RuleLabExactPair {
76
- id?: string;
77
- binding_kind?: UnityResourceBinding['kind'];
78
- draft_rule_id?: string;
79
- source_anchor: RuleLabExactPairAnchor;
80
- target_anchor: RuleLabExactPairAnchor;
81
- }
82
- export interface RuleDslMatch {
83
- trigger_tokens: string[];
84
- symbol_kind?: string[];
85
- module_scope?: string[];
86
- resource_types?: string[];
87
- host_base_type?: string[];
88
- }
89
- export interface RuleDslTopologyHop {
90
- hop: string;
91
- from: Record<string, unknown>;
92
- to: Record<string, unknown>;
93
- edge: {
94
- kind: string;
95
- };
96
- constraints?: Record<string, unknown>;
97
- }
98
- export interface RuleDslClosure {
99
- required_hops: string[];
100
- failure_map: Partial<Record<string, RuntimeClaimFailureReason>>;
101
- }
102
- export interface RuleDslClaims {
103
- guarantees: string[];
104
- non_guarantees: string[];
105
- next_action: string;
106
- }
107
- export interface UnityResourceBinding {
108
- kind: 'asset_ref_loads_components' | 'method_triggers_field_load' | 'method_triggers_scene_load' | 'method_triggers_method';
109
- description?: string;
110
- ref_field_pattern?: string;
111
- target_entry_points?: string[];
112
- host_class_pattern?: string;
113
- field_name?: string;
114
- loader_methods?: string[];
115
- scene_name?: string;
116
- source_class_pattern?: string;
117
- source_method?: string;
118
- target_class_pattern?: string;
119
- target_method?: string;
120
- }
121
- export interface LifecycleOverrides {
122
- additional_entry_points?: string[];
123
- scope?: string;
124
- }
125
- export interface RuleDslDraft {
126
- id: string;
127
- version: string;
128
- description?: string;
129
- match: RuleDslMatch;
130
- topology: RuleDslTopologyHop[];
131
- closure: RuleDslClosure;
132
- claims: RuleDslClaims;
133
- resource_bindings?: UnityResourceBinding[];
134
- lifecycle_overrides?: LifecycleOverrides;
135
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,64 +0,0 @@
1
- # Unity Rule Authoring Contract
2
-
3
- ## Scope
4
-
5
- This contract defines the stable public authoring workflow for
6
- `gitnexus-unity-rule-gen`.
7
-
8
- The only public path is direct rule authoring and validation:
9
-
10
- `approved/*.yaml -> rule-lab compile -> analyze -> CLI validation`
11
-
12
- ## Workflow Position
13
-
14
- 1. `gap-lab` is historical context only and not part of the active workflow.
15
- 2. Default authoring path is reduced `rule-lab` for sparse irregular gaps.
16
- 3. Query-time runtime closure remains graph-only.
17
-
18
- ## Input Schema
19
-
20
- Each authoring item must be an exact source/target pair (or explicit pair set):
21
-
22
- - `source_class`
23
- - `source_method`
24
- - `target_class`
25
- - `target_method`
26
- - `expected_missing_hop` (short text)
27
-
28
- If multiple anchors match, user must select the intended anchor explicitly.
29
- Auto-guessing ambiguous anchors is forbidden.
30
-
31
- ## Mandatory Guards
32
-
33
- 1. Duplicate-prevention:
34
- - Block proposals already covered by `.gitnexus/rules/approved/*.yaml`.
35
- 2. Fail-closed binding resolution:
36
- - Unresolved bindings block progress.
37
- - `UnknownClass` / `UnknownMethod` placeholders are forbidden.
38
- 3. Non-empty evidence before promote:
39
- - `confirmed_chain.steps` (or equivalent) must be non-empty.
40
-
41
- ## Artifact Expectations
42
-
43
- Primary artifacts are under `.gitnexus/rules/lab/runs/<run_id>/...`.
44
-
45
- Run/slice identifiers are internal artifact locators. Public operator guidance must
46
- not require run orchestration as the primary flow.
47
-
48
- ## Event/Delegate Boundary
49
-
50
- Event/delegate system-wide coverage is analyzer-native scope:
51
-
52
- - capture `assignment_expression` (`+=`, `-=`)
53
- - index delegate/action field symbols
54
- - capture generic event-type metadata (`Raise<T>` / `Listen<T>`)
55
-
56
- Rule authoring is only for sparse, explicitly scoped residual gaps.
57
-
58
- ## Verification Contract
59
-
60
- 1. Promote only after mandatory guards pass.
61
- 2. Compile approved rules before analyze.
62
- 3. Verify in a fresh CLI process (`gitnexus cypher` / `gitnexus query`).
63
- 4. Under `hydration_policy=strict` with `fallbackToCompact=true`, parity rerun
64
- is required before final closure conclusion.
@@ -1,107 +0,0 @@
1
- ---
2
- name: gitnexus-unity-rule-gen
3
- description: "Reduced rule-lab workflow for Unity analyze_rules authoring from exact source/target gaps. Use when: 'create unity rules', 'generate analyze rules', 'fill sparse runtime gap'."
4
- ---
5
-
6
- # Unity Reduced Rule-Lab Authoring
7
-
8
- This skill is the post-rollback workflow.
9
-
10
- Primary path:
11
-
12
- 1. Gather user-confirmed exact source/target pair(s).
13
- 2. Curate/promote to `rules/approved/*.yaml`.
14
- 3. Compile approved rules.
15
- 4. Re-run analyze and verify via CLI graph checks (not MCP session query/context).
16
-
17
- `gap-lab` is migration history only and is not part of active operator guidance.
18
-
19
- Read first:
20
-
21
- - `gitnexus/skills/_shared/unity-rule-authoring-contract.md`
22
- - `docs/unity-runtime-process-source-of-truth.md`
23
- - `docs/gap-lab-rule-lab-architecture.md`
24
-
25
- ## Hard Boundaries
26
-
27
- 1. Query-time runtime closure remains graph-only.
28
- 2. Event/delegate large-scale gaps are analyzer work, not rule-authoring work.
29
- 3. This skill is for sparse irregular gaps only.
30
-
31
- ## Input Contract (required)
32
-
33
- Provide exact pair intent for each candidate:
34
-
35
- - source class + source method
36
- - target class + target method
37
- - expected missing runtime hop
38
-
39
- If anchors are ambiguous (multiple candidate methods/classes), stop and ask user to choose explicit options. Do not auto-guess.
40
-
41
- ## Direct Public Flow
42
-
43
- ### Phase A: Prepare exact pairs
44
-
45
- 1. Confirm repo and index freshness.
46
- 2. Normalize candidate pairs into explicit source/target tuples.
47
- 3. Run duplicate precheck against `.gitnexus/rules/approved/*.yaml`.
48
-
49
- ### Phase B: Review and curate
50
-
51
- ```bash
52
- gitnexus rule-lab analyze --repo-path "$REPO_PATH"
53
- RUN_ID="$(ls -1t "$REPO_PATH/.gitnexus/rules/lab/runs" | head -n 1)"
54
- SLICE_ID="$(find "$REPO_PATH/.gitnexus/rules/lab/runs/$RUN_ID/slices" -name 'slice.json' -maxdepth 2 | head -n 1 | xargs -I{} basename "$(dirname "{}")")"
55
- gitnexus rule-lab review-pack --repo-path "$REPO_PATH" --run-id "$RUN_ID" --slice-id "$SLICE_ID"
56
- gitnexus rule-lab curate --repo-path "$REPO_PATH" --run-id "$RUN_ID" --slice-id "$SLICE_ID" --input-path "$CURATION_JSON_PATH"
57
- ```
58
-
59
- Use `analyze` as proposal generation for exact pairs, then curate/promote only proposals that pass guards.
60
- Do not ask users to provide `run-id`/`slice-id`; resolve them from generated artifacts.
61
-
62
- ### Phase C: Promote approved rule
63
-
64
- ```bash
65
- gitnexus rule-lab promote --repo-path "$REPO_PATH" --run-id "$RUN_ID" --slice-id "$SLICE_ID"
66
- ```
67
-
68
- ### Phase D: Compile and re-index
69
-
70
- ```bash
71
- gitnexus rule-lab compile --repo-path "$REPO_PATH" --family analyze_rules
72
- gitnexus analyze -f "$REPO_PATH"
73
- ```
74
-
75
- ## Three Mandatory Guards
76
-
77
- 1. Duplicate-prevention:
78
- - Block if pair already covered by `rules/approved/*.yaml`.
79
- 2. Fail-closed binding resolution:
80
- - Block if unresolved binding remains.
81
- - `UnknownClass` / `UnknownMethod` placeholders are forbidden.
82
- 3. Non-empty evidence before promote:
83
- - `confirmed_chain.steps` (or equivalent) must be non-empty.
84
-
85
- ## Verification
86
-
87
- 1. Verify synthetic edges with **CLI in a fresh process** (for example `gitnexus cypher` / `gitnexus query`).
88
- 2. Do not use current MCP session `query/context` as synthetic-edge acceptance evidence immediately after analyze/rebuild.
89
- 3. Inspect analyze summary `rule_binding.*` diagnostics:
90
- - `rule_binding.agent_report: should_report=false` → no anomaly to report.
91
- - `rule_binding.agent_report: should_report=true` → summarize `rule_binding.anomaly:*` in your run report.
92
- 4. Keep closure claims aligned to graph-only semantics.
93
- 5. Under `hydration_policy=strict` with `fallbackToCompact=true`, run parity before final closure conclusion.
94
-
95
- Suggested acceptance check (example):
96
-
97
- ```bash
98
- gitnexus cypher --repo "$REPO_ALIAS" \
99
- "MATCH (a)-[r:CodeRelation {type:'CALLS'}]->(b)
100
- WHERE r.reason STARTS WITH 'unity-rule-'
101
- RETURN a.name, b.name, r.reason
102
- LIMIT 50"
103
- ```
104
-
105
- ## Legacy Note
106
-
107
- If historical `.gitnexus/gap-lab/runs/**` artifacts exist, treat them as migration evidence only. Do not require gap-lab parity/coverage gates for direct `approved -> compile -> analyze -> CLI validation` loops.